Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 43215

History | View | Annotate | Download (85.1 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

    
25
package org.gvsig.fmap.dal.feature.impl;
26

    
27
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
28

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

    
41
import org.cresques.cts.IProjection;
42

    
43
import org.gvsig.fmap.dal.DALLocator;
44
import org.gvsig.fmap.dal.DataManager;
45
import org.gvsig.fmap.dal.DataQuery;
46
import org.gvsig.fmap.dal.DataServerExplorer;
47
import org.gvsig.fmap.dal.DataSet;
48
import org.gvsig.fmap.dal.DataStore;
49
import org.gvsig.fmap.dal.DataStoreNotification;
50
import org.gvsig.fmap.dal.DataStoreParameters;
51
import org.gvsig.fmap.dal.DataStoreProviderFactory;
52
import org.gvsig.fmap.dal.ExpressionEvaluator;
53
import org.gvsig.fmap.dal.exception.CloneException;
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.ReadException;
60
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
61
import org.gvsig.fmap.dal.exception.WriteException;
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.FeatureStoreTimeSupport;
81
import org.gvsig.fmap.dal.feature.FeatureStoreTransform;
82
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
83
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
84
import org.gvsig.fmap.dal.feature.exception.CreateFeatureException;
85
import org.gvsig.fmap.dal.feature.exception.DataExportException;
86
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
87
import org.gvsig.fmap.dal.feature.exception.FinishEditingException;
88
import org.gvsig.fmap.dal.feature.exception.GetFeatureTypeException;
89
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureException;
90
import org.gvsig.fmap.dal.feature.exception.IllegalFeatureTypeException;
91
import org.gvsig.fmap.dal.feature.exception.NeedEditingModeException;
92
import org.gvsig.fmap.dal.feature.exception.NoNewFeatureInsertException;
93
import org.gvsig.fmap.dal.feature.exception.NullFeatureTypeException;
94
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
95
import org.gvsig.fmap.dal.feature.exception.PersistenceCantFindFeatureTypeException;
96
import org.gvsig.fmap.dal.feature.exception.PersistenceStoreAlreadyLoadedException;
97
import org.gvsig.fmap.dal.feature.exception.SelectionNotAllowedException;
98
import org.gvsig.fmap.dal.feature.exception.StoreCancelEditingException;
99
import org.gvsig.fmap.dal.feature.exception.StoreDeleteEditableFeatureException;
100
import org.gvsig.fmap.dal.feature.exception.StoreDeleteFeatureException;
101
import org.gvsig.fmap.dal.feature.exception.StoreEditException;
102
import org.gvsig.fmap.dal.feature.exception.StoreInsertFeatureException;
103
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureException;
104
import org.gvsig.fmap.dal.feature.exception.StoreUpdateFeatureTypeException;
105
import org.gvsig.fmap.dal.feature.exception.ValidateFeaturesException;
106
import org.gvsig.fmap.dal.feature.exception.WriteNotAllowedException;
107
import org.gvsig.fmap.dal.feature.impl.expansionadapter.MemoryExpansionAdapter;
108
import org.gvsig.fmap.dal.feature.impl.featureset.DefaultFeatureSet;
109
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
110
import org.gvsig.fmap.dal.feature.impl.undo.DefaultFeatureCommandsStack;
111
import org.gvsig.fmap.dal.feature.impl.undo.FeatureCommandsStack;
112
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
113
import org.gvsig.fmap.dal.feature.spi.DefaultFeatureProvider;
114
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
115
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
116
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
117
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
118
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider_v2;
119
import org.gvsig.fmap.dal.feature.spi.cache.FeatureCacheProvider;
120
import org.gvsig.fmap.dal.feature.spi.index.FeatureIndexProviderServices;
121
import org.gvsig.fmap.dal.impl.DefaultDataManager;
122
import org.gvsig.fmap.dal.resource.Resource;
123
import org.gvsig.fmap.dal.spi.DataStoreInitializer2;
124
import org.gvsig.fmap.dal.spi.DataStoreProvider;
125
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
126
import org.gvsig.fmap.geom.primitive.Envelope;
127
import org.gvsig.metadata.MetadataLocator;
128
import org.gvsig.metadata.MetadataManager;
129
import org.gvsig.metadata.exceptions.MetadataException;
130
import org.gvsig.timesupport.Interval;
131
import org.gvsig.tools.ToolsLocator;
132
import org.gvsig.tools.dispose.DisposableIterator;
133
import org.gvsig.tools.dispose.impl.AbstractDisposable;
134
import org.gvsig.tools.dynobject.DelegatedDynObject;
135
import org.gvsig.tools.dynobject.DynClass;
136
import org.gvsig.tools.dynobject.DynObject;
137
import org.gvsig.tools.dynobject.DynObjectManager;
138
import org.gvsig.tools.dynobject.DynStruct;
139
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
140
import org.gvsig.tools.dynobject.exception.DynMethodException;
141
import org.gvsig.tools.exception.BaseException;
142
import org.gvsig.tools.exception.NotYetImplemented;
143
import org.gvsig.tools.identitymanagement.SimpleIdentityManager;
144
import org.gvsig.tools.observer.Observable;
145
import org.gvsig.tools.observer.Observer;
146
import org.gvsig.tools.observer.impl.DelegateWeakReferencingObservable;
147
import org.gvsig.tools.persistence.PersistenceManager;
148
import org.gvsig.tools.persistence.Persistent;
149
import org.gvsig.tools.persistence.PersistentState;
150
import org.gvsig.tools.persistence.exception.PersistenceException;
151
import org.gvsig.tools.undo.RedoException;
152
import org.gvsig.tools.undo.UndoException;
153
import org.gvsig.tools.undo.command.Command;
154
import org.gvsig.tools.util.HasAFile;
155
import org.gvsig.tools.visitor.Visitor;
156

    
157
import org.slf4j.Logger;
158
import org.slf4j.LoggerFactory;
159

    
160
public class DefaultFeatureStore extends AbstractDisposable implements
161
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
162

    
163
    private static final Logger LOG = LoggerFactory
164
        .getLogger(DefaultFeatureStore.class);
165

    
166
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
167

    
168
    private DataStoreParameters parameters = null;
169
    private FeatureSelection selection;
170
    private FeatureLocks locks;
171

    
172
    private DelegateWeakReferencingObservable delegateObservable =
173
        new DelegateWeakReferencingObservable(this);
174

    
175
    private FeatureCommandsStack commands;
176
    private FeatureTypeManager featureTypeManager;
177
    private FeatureManager featureManager;
178
    private SpatialManager spatialManager;
179

    
180
    private FeatureType defaultFeatureType = null;
181
    private List featureTypes = new ArrayList();
182

    
183
    private int mode = MODE_QUERY;
184
    private long versionOfUpdate = 0;
185
    private boolean hasStrongChanges = true;
186
    private boolean hasInserts = true;
187

    
188
    private DefaultDataManager dataManager = null;
189

    
190
    private FeatureStoreProvider provider = null;
191

    
192
    private DefaultFeatureIndexes indexes;
193

    
194
    private DefaultFeatureStoreTransforms transforms;
195

    
196
    DelegatedDynObject metadata;
197

    
198
    private Set metadataChildren;
199

    
200
    private Long featureCount = null;
201

    
202
    private long temporalOid = 0;
203

    
204
    private FeatureCacheProvider cache;
205

    
206
    StateInformation state;
207
    
208
    FeatureStoreTimeSupport timeSupport;
209

    
210

    
211
    private class StateInformation extends HashMap<Object, Object> {
212

    
213
        private static final long serialVersionUID = 4109026189635185666L;
214

    
215
        private boolean broken;
216
        private Throwable breakingsCause;
217
    
218
        public StateInformation() {
219
            this.clear();
220
        }
221
        
222
        @Override
223
        public void clear() {
224
            this.broken = false;
225
            this.breakingsCause = null;
226
            super.clear();
227
        }
228
        
229
        public boolean isBroken() {
230
            return this.broken;
231
        }
232
        
233
        public void broken() {
234
            this.broken = true;
235
        }
236
        
237
        public Throwable getBreakingsCause() {
238
            return this.breakingsCause;
239
        }
240
        
241
        public void setBreakingsCause(Throwable cause) {
242
            if( this.breakingsCause==null ) {
243
                this.breakingsCause = cause;
244
            }
245
            this.broken = true;
246
        }        
247
    }
248
    
249

    
250

    
251
    /*
252
     * TODO:
253
     *
254
     * - Comprobar que solo se pueden a?adir reglas de validacion sobre un
255
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
256
     * featureType al que se le han cambiado las reglas de validacion cuando
257
     * hasStrongChanges=false.
258
     */
259

    
260
    public DefaultFeatureStore() {
261
        this.state = new StateInformation();
262
    }
263

    
264
    @Override
265
    public void intialize(DataManager dataManager,
266
        DataStoreParameters parameters) throws InitializeException {
267

    
268
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
269

    
270
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
271
            FeatureStore.METADATA_DEFINITION_NAME,
272
            MetadataManager.METADATA_NAMESPACE
273
        );
274

    
275
        this.dataManager = (DefaultDataManager) dataManager;
276

    
277
        this.parameters = parameters;
278
        this.transforms = new DefaultFeatureStoreTransforms(this);
279
        try {
280
            indexes = new DefaultFeatureIndexes(this);
281
        } catch (DataException e) {
282
            throw new InitializeException(e);
283
        }
284

    
285
    }
286

    
287
    @Override
288
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
289
        this.provider = (FeatureStoreProvider) provider;
290
        this.delegate((DynObject) provider);
291
        this.metadataChildren = new HashSet();
292
        this.metadataChildren.add(provider);
293
    }
294

    
295
    @Override
296
    public DataStoreParameters getParameters() {
297
        return parameters;
298
    }
299

    
300
    public int getMode() {
301
        return this.mode;
302
    }
303

    
304
    @Override
305
    public DataManager getManager() {
306
        return this.dataManager;
307
    }
308

    
309
    @Override
310
    public Iterator getChildren() {
311
        return this.provider.getChilds();
312
    }
313

    
314
    @Override
315
    public FeatureStoreProvider getProvider() {
316
        return this.provider;
317
    }
318

    
319
    public FeatureManager getFeatureManager() {
320
        return this.featureManager;
321
    }
322

    
323
    @Override
324
    public void setFeatureTypes(List types, FeatureType defaultType) {
325
        this.featureTypes = types;
326
        this.defaultFeatureType = defaultType;
327
    }
328

    
329
    public void open() throws OpenException {
330
        if (this.mode != MODE_QUERY) {
331
            // TODO: Se puede hacer un open estando en edicion ?
332
            try {
333
                throw new IllegalStateException();
334
            } catch(Exception ex) {
335
                LOG.warn("Opening a store in editing/append mode ("+this.getFullName()+").",ex);
336
            }
337
        }
338
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
339
        this.provider.open();
340
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
341
    }
342

    
343
    @Override
344
    public void refresh() throws OpenException, InitializeException {
345
        if (this.mode != MODE_QUERY) {
346
            throw new IllegalStateException();
347
        }
348
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
349
        if( state.isBroken() ) {
350
            this.load(state);
351
        } else {
352
            this.featureCount = null;
353
            this.provider.refresh();
354
        }
355
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
356
    }
357

    
358
    public void close() throws CloseException {
359
        if (this.mode != MODE_QUERY) {
360
            // TODO: Se puede hacer un close estando en edicion ?
361
            try {
362
                throw new IllegalStateException();
363
            } catch(Exception ex) {
364
                LOG.warn("Clossing a store in editing/append mode ("+this.getFullName()+").",ex);
365
            }
366
        }
367
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
368
        this.featureCount = null;
369
        this.provider.close();
370
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
371
    }
372

    
373
    @Override
374
    protected void doDispose() throws BaseException {
375
        if (this.mode != MODE_QUERY) {
376
            // TODO: Se puede hacer un dispose estando en edicion ?
377
            try {
378
                throw new IllegalStateException();
379
            } catch(Exception ex) {
380
                LOG.warn("Dispossing a store in editing/append mode ("+this.getFullName()+").",ex);
381
            }
382
        }
383
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
384
        this.disposeIndexes();
385
        this.provider.dispose();
386
        if (this.selection != null) {
387
            this.selection.dispose();
388
            this.selection = null;
389
        }
390
        this.commands = null;
391
        this.featureCount = null;
392
        if (this.locks != null) {
393
            // this.locks.dispose();
394
            this.locks = null;
395
        }
396

    
397
        if (this.featureTypeManager != null) {
398
            this.featureTypeManager.dispose();
399
            this.featureTypeManager = null;
400
        }
401

    
402
        this.featureManager = null;
403
        this.spatialManager = null;
404

    
405
        this.parameters = null;
406
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
407
        if (delegateObservable != null) {
408
            this.delegateObservable.deleteObservers();
409
            this.delegateObservable = null;
410
        }
411
    }
412

    
413
    @Override
414
    public boolean allowWrite() {
415
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
416
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
417
            return false;
418
        }
419
        return this.provider.allowWrite();
420
    }
421

    
422
    @Override
423
    public boolean canWriteGeometry(int geometryType) throws DataException {
424
        return this.provider.canWriteGeometry(geometryType, 0);
425
    }
426

    
427
    @Override
428
    public DataServerExplorer getExplorer() throws ReadException,
429
        ValidateDataParametersException {
430
        if( this.state.isBroken() ) {
431
            try {
432
                return this.provider.getExplorer();
433
            } catch(Throwable th) {
434
                return null;
435
            }
436
        } else {
437
            return this.provider.getExplorer();
438
        }
439
    }
440

    
441
    /*
442
     * public Metadata getMetadata() throws MetadataNotFoundException {
443
     * // TODO:
444
     * // Si el provider devuelbe null habria que ver de construir aqui
445
     * // los metadatos basicos, como el Envelope y el SRS.
446
     *
447
     * // TODO: Estando en edicion el Envelope deberia de
448
     * // actualizarse usando el spatialManager
449
     * return this.provider.getMetadata();
450
     * }
451
     */
452

    
453
    @Override
454
    public Envelope getEnvelope() throws DataException {
455
        if (this.mode == MODE_FULLEDIT) {
456
                // Just in case another thread tries to write in the store
457
                synchronized (this) {
458
                        return this.spatialManager.getEnvelope();
459
                        }
460
        }
461
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
462
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
463
        }
464
        return this.provider.getEnvelope();
465
    }
466

    
467
    /**
468
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
469
     */
470
    @Override
471
    public IProjection getSRSDefaultGeometry() throws DataException {
472
        return this.getDefaultFeatureType().getDefaultSRS();
473
    }
474

    
475
    @Override
476
    public FeatureSelection createDefaultFeatureSelection()
477
        throws DataException {
478
        return new DefaultFeatureSelection(this);
479
    }
480

    
481
    @Override
482
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
483
        throws DataException {
484
        if (type.hasOID()) {
485
            return new DefaultFeatureProvider(type,
486
                this.provider.createNewOID());
487
        }
488
        return new DefaultFeatureProvider(type);
489
    }
490

    
491
    @Override
492
    public void saveToState(PersistentState state) throws PersistenceException {
493
        /*if (this.mode != FeatureStore.MODE_QUERY) {
494
            throw new PersistenceException(new IllegalStateException(
495
                this.getName()));
496
        }*/
497
        state.set("dataStoreName", this.getName());
498
        state.set("parameters", this.parameters);
499
        state.set("selection", this.selection);
500
        state.set("transforms", this.transforms);
501
        // TODO locks persistence
502
        // state.set("locks", this.locks);
503
        // TODO indexes persistence
504
        // state.set("indexes", this.indexes);
505
        Map evaluatedAttr = new HashMap(1);
506
        Iterator iterType = featureTypes.iterator();
507
        Iterator iterAttr;
508
        FeatureType type;
509
        DefaultFeatureAttributeDescriptor attr;
510
        List attrs;
511
        while (iterType.hasNext()) {
512
            type = (FeatureType) iterType.next();
513
            attrs = new ArrayList();
514
            iterAttr = type.iterator();
515
            while (iterAttr.hasNext()) {
516
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
517
                if ((attr.getEvaluator() != null)
518
                    && (attr.getEvaluator() instanceof Persistent)) {
519
                    attrs.add(attr);
520
                }
521
            }
522
            if (!attrs.isEmpty()) {
523
                evaluatedAttr.put(type.getId(), attrs);
524
            }
525

    
526
        }
527

    
528
        if (evaluatedAttr.isEmpty()) {
529
            evaluatedAttr = null;
530
        }
531

    
532
        state.set("evaluatedAttributes", evaluatedAttr);
533
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
534

    
535
    }
536
    
537
    @Override
538
    public void loadFromState(final PersistentState persistentState)
539
        throws PersistenceException {
540
        if (this.provider != null) {
541
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
542
        }
543
        if (this.getManager() == null) {
544
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
545
        }
546
        state.clear();
547
        try {
548
            state.put("parameters", persistentState.get("parameters"));
549
        } catch(Throwable th) {
550
            state.setBreakingsCause(th);
551
        }
552
        try {
553
            state.put("selection", persistentState.get("selection"));
554
        } catch(Throwable th) {
555
            state.setBreakingsCause(th);
556
        }
557
        try {
558
            state.put("transforms",  persistentState.get("transforms"));
559
        } catch(Throwable th) {
560
            state.setBreakingsCause(th);
561
        }
562
        try {
563
            state.put("evaluatedAttributes",  persistentState.get("evaluatedAttributes"));
564
        } catch(Throwable th) {
565
            state.setBreakingsCause(th);
566
        }
567
        try {
568
            state.put("defaultFeatureTypeId", persistentState.getString("defaultFeatureTypeId"));
569
        } catch(Throwable th) {
570
            state.setBreakingsCause(th);
571
        }
572
        load(state);
573
    }        
574
        
575
    private void load(StateInformation state) {   
576
        this.featureTypes = new ArrayList();
577
        this.defaultFeatureType = null;
578
        this.featureCount = null;
579

    
580
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
581
        try {
582
            intialize(dataManager, params);
583
        } catch(Throwable th) {
584
            state.setBreakingsCause(th);
585
        }
586

    
587
        try {
588
            DataStoreProvider prov = dataManager.createProvider(
589
                getStoreProviderServices(),
590
                params
591
            );
592
            setProvider(prov);
593
        } catch(Throwable th) {
594
            state.setBreakingsCause(th);
595
        }
596

    
597
        try {
598
            selection = (FeatureSelection) state.get("selection");
599
        } catch(Throwable th) {
600
            state.setBreakingsCause(th);
601
        }
602

    
603
        try {
604
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
605
            this.transforms.setFeatureStore(this);
606
            for( FeatureStoreTransform transform : this.transforms ) {
607
                try {
608
                    transform.setUp();
609
                } catch(Throwable th) {
610
                    state.setBreakingsCause(th);
611
                }
612
            }
613
        } catch(Throwable th) {
614
            state.setBreakingsCause(th);
615
        }
616

    
617
        try {
618
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
619
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
620
                    Iterator iterEntries = evaluatedAttributes.entrySet().iterator();
621
                    while (iterEntries.hasNext()) {
622
                            Entry entry = (Entry) iterEntries.next();
623
                            List attrs = (List) entry.getValue();
624
                            if (attrs.isEmpty()) {
625
                                    continue;
626
                            }
627
                            int fTypePos = -1;
628
                            DefaultFeatureType type = null;
629
                            for (int i = 0; i < featureTypes.size(); i++) {
630
                                    type = (DefaultFeatureType) featureTypes.get(i);
631
                                    if (type.getId().equals(entry.getKey())) {
632
                                            fTypePos = i;
633
                                            break;
634
                                    }
635
                            }
636
                            if (type == null) {
637
                                    throw new PersistenceCantFindFeatureTypeException(
638
                                            getName(), (String) entry.getKey());
639
                            }
640
                            DefaultEditableFeatureType eType = (DefaultEditableFeatureType) type.getEditable();
641
                            Iterator<FeatureAttributeDescriptor> iterAttr = attrs.iterator();
642
                            while (iterAttr.hasNext()) {
643
                                    FeatureAttributeDescriptor attr = iterAttr.next();
644
                                    eType.addLike(attr);
645
                            }
646
                            featureTypes.set(fTypePos, eType.getNotEditableCopy());
647

    
648
                    }
649

    
650
            }
651
        } catch(Throwable th) {
652
            state.setBreakingsCause(th);
653
        }
654

    
655
                                
656
        try {
657
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
658
            FeatureType ftype;
659

    
660
            if (defaultFeatureType == null ||
661
                    defaultFeatureType.getId() == null ||
662
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
663

    
664
                    ftype = getFeatureType(defaultFeatureTypeId);
665
                    if (ftype == null) {
666
                            /*
667
                             * Un error en el m?todo de PostgreSQL getName(), hace que
668
                             * el nombre del featureType sea valor retornado por el getProviderName()
669
                             * De momento se pone este parche para apa?arlo y poder mantener compatibilidad
670
                             * con proyectos antiguos (2.1 y 2.2)
671
                             */
672
                            ftype = getFeatureType(getName());
673
                            if(ftype == null ) {
674
                                    throw new RuntimeException("Can't locate feature type");
675
                            }
676
                    }
677
                    defaultFeatureType = ftype;
678
            }
679
        } catch(Throwable th) {
680
            state.setBreakingsCause(th);
681
        }
682

    
683
        LOG.info("load() broken:{}, {}, {}.", 
684
                new Object[] { state.isBroken(), this.getProviderName(), params }
685
        );
686
    }
687

    
688
        public DataStoreProviderServices getStoreProviderServices() {
689
                return this;
690
        }
691
        
692
    public static void registerPersistenceDefinition() {
693
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
694
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
695
            DynStruct definition =
696
                manager.addDefinition(DefaultFeatureStore.class,
697
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
698
                        + " Persistent definition", null, null);
699
            definition.addDynFieldString("dataStoreName").setMandatory(true)
700
                .setPersistent(true);
701

    
702
            definition.addDynFieldObject("parameters")
703
                .setClassOfValue(DynObject.class).setMandatory(true)
704
                .setPersistent(true);
705

    
706
            definition.addDynFieldObject("selection")
707
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
708
                .setPersistent(true);
709

    
710
            definition.addDynFieldObject("transforms")
711
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
712
                .setMandatory(true).setPersistent(true);
713

    
714
            definition.addDynFieldMap("evaluatedAttributes")
715
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
716
                .setMandatory(false).setPersistent(true);
717

    
718
            definition.addDynFieldString("defaultFeatureTypeId")
719
                .setMandatory(true).setPersistent(true);
720
        }
721
    }
722

    
723
    public static void registerMetadataDefinition() throws MetadataException {
724
        MetadataManager manager = MetadataLocator.getMetadataManager();
725
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
726
            DynStruct metadataDefinition =
727
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
728
            metadataDefinition.extend(manager
729
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
730
        }
731
    }
732

    
733
    //
734
    // ====================================================================
735
    // Gestion de la seleccion
736
    //
737

    
738
    @Override
739
    public void setSelection(DataSet selection) throws DataException {
740
        this.setSelection((FeatureSet) selection);
741
    }
742

    
743
    @Override
744
    public DataSet createSelection() throws DataException {
745
        return createFeatureSelection();
746
    }
747

    
748
    @Override
749
    public DataSet getSelection() throws DataException {
750
        return this.getFeatureSelection();
751
    }
752

    
753
    @Override
754
    public void setSelection(FeatureSet selection) throws DataException {
755
        setSelection(selection, true);
756
    }
757

    
758
    public void setSelection(FeatureSet selection, boolean undoable)
759
        throws DataException {
760
        if (selection == null) {
761
            if (undoable) {
762
                throw new SelectionNotAllowedException(getName());
763
            }
764

    
765
        } else {
766
            if (selection.equals(this.selection)) {
767
                return;
768
            }
769
            if (!selection.isFromStore(this)) {
770
                throw new SelectionNotAllowedException(getName());
771
            }
772
        }
773

    
774
        if (this.selection != null) {
775
            this.selection.deleteObserver(this);
776
        }
777
        if (selection == null) {
778
            if (this.selection != null) {
779
                this.selection.dispose();
780
            }
781
            this.selection = null;
782
            return;
783
        }
784
        if (selection instanceof FeatureSelection) {
785
            if (undoable && isEditing()) {
786
                commands.selectionSet(this, this.selection,
787
                    (FeatureSelection) selection);
788
            }
789
            if (this.selection != null) {
790
                this.selection.dispose();
791
            }
792
            this.selection = (FeatureSelection) selection;
793
        } else {
794
            if (undoable && isEditing()) {
795
                commands.startComplex("_selectionSet");
796
            }
797
            if (selection instanceof DefaultFeatureSelection) {
798
                DefaultFeatureSelection defSelection =
799
                    (DefaultFeatureSelection) selection;
800
                defSelection.deselectAll(undoable);
801
                defSelection.select(selection, undoable);
802
            } else {
803
                this.selection.deselectAll();
804
                this.selection.select(selection);
805
            }
806
            if (undoable && isEditing()) {
807
                commands.endComplex();
808
            }
809
        }
810
        this.selection.addObserver(this);
811

    
812
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
813
    }
814

    
815
    @Override
816
    public FeatureSelection createFeatureSelection() throws DataException {
817
        return this.provider.createFeatureSelection();
818
    }
819

    
820
    @Override
821
    public FeatureSelection getFeatureSelection() throws DataException {
822
        if (selection == null) {
823
            this.selection = createFeatureSelection();
824
            this.selection.addObserver(this);
825
        }
826
        return selection;
827
    }
828

    
829
    //
830
    // ====================================================================
831
    // Gestion de notificaciones
832
    //
833

    
834
    @Override
835
    public void notifyChange(FeatureStoreNotification storeNotification) {
836
        try {
837
            delegateObservable.notifyObservers(storeNotification);
838
        } catch (Throwable ex) {
839
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
840
        }
841
    }
842

    
843
    @Override
844
    public void notifyChange(String notification) {
845
        if (delegateObservable != null) {
846
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
847
        }
848

    
849
    }
850

    
851
    @Override
852
    public void notifyChange(String notification, FeatureProvider data) {
853
        Feature f = null;
854
        try {
855
            f = createFeature(data);
856
        } catch (Throwable ex) {
857
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
858
        }
859
        notifyChange(notification, f);
860
    }
861

    
862
    public void notifyChange(String notification, Feature feature) {
863
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
864
            feature));
865
    }
866

    
867
    public void notifyChange(String notification, Command command) {
868
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
869
            command));
870
    }
871

    
872
    public void notifyChange(String notification, EditableFeatureType type) {
873
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
874
            type));
875
    }
876

    
877
    @Override
878
    public void notifyChange(String notification, Resource resource) {
879
        notifyChange(new DefaultFeatureStoreNotification(this,
880
            DataStoreNotification.RESOURCE_CHANGED));
881
    }
882

    
883
    //
884
    // ====================================================================
885
    // Gestion de bloqueos
886
    //
887

    
888
    @Override
889
    public boolean isLocksSupported() {
890
        return this.provider.isLocksSupported();
891
    }
892

    
893
    @Override
894
    public FeatureLocks getLocks() throws DataException {
895
        if (!this.provider.isLocksSupported()) {
896
            LOG.warn("Locks not supported");
897
            return null;
898
        }
899
        if (locks == null) {
900
            this.locks = this.provider.createFeatureLocks();
901
        }
902
        return locks;
903
    }
904

    
905
    //
906
    // ====================================================================
907
    // Interface Observable
908
    //
909

    
910
    @Override
911
    public void disableNotifications() {
912
        this.delegateObservable.disableNotifications();
913

    
914
    }
915

    
916
    @Override
917
    public void enableNotifications() {
918
        this.delegateObservable.enableNotifications();
919
    }
920

    
921
    @Override
922
    public void beginComplexNotification() {
923
        this.delegateObservable.beginComplexNotification();
924

    
925
    }
926

    
927
    @Override
928
    public void endComplexNotification() {
929
        this.delegateObservable.endComplexNotification();
930

    
931
    }
932

    
933
    @Override
934
    public void addObserver(Observer observer) {
935
        if (delegateObservable != null) {
936
            this.delegateObservable.addObserver(observer);
937
        }
938
    }
939

    
940
    @Override
941
    public void deleteObserver(Observer observer) {
942
        if (delegateObservable != null) {
943
            this.delegateObservable.deleteObserver(observer);
944
        }
945
    }
946

    
947
    @Override
948
    public void deleteObservers() {
949
        this.delegateObservable.deleteObservers();
950

    
951
    }
952

    
953
    //
954
    // ====================================================================
955
    // Interface Observer
956
    //
957
    // Usado para observar:
958
    // - su seleccion
959
    // - sus bloqueos
960
    // - sus recursos
961
    //
962

    
963
    @Override
964
    public void update(Observable observable, Object notification) {
965
        if (observable instanceof FeatureSet) {
966
            if (observable == this.selection) {
967
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
968
            } else
969
                if (observable == this.locks) {
970
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
971
                }
972

    
973
        } else
974
            if (observable instanceof FeatureStoreProvider) {
975
                if (observable == this.provider) {
976

    
977
                }
978

    
979
            }
980
    }
981

    
982
    //
983
    // ====================================================================
984
    // Edicion
985
    //
986

    
987
    private void newVersionOfUpdate() {
988
        this.versionOfUpdate++;
989
    }
990

    
991
    private long currentVersionOfUpdate() {
992
        return this.versionOfUpdate;
993
    }
994

    
995
    private void checkInEditingMode() throws NeedEditingModeException {
996
        if (mode != MODE_FULLEDIT) {
997
            throw new NeedEditingModeException(this.getName());
998
        }
999
    }
1000

    
1001
    private void checkNotInAppendMode() throws IllegalStateException {
1002
        if (mode == MODE_APPEND) {
1003
                        throw new IllegalStateException("Error: store "
1004
                                        + this.getFullName() + " is in append mode");
1005
        }
1006
    }
1007

    
1008
    private void checkIsOwnFeature(Feature feature)
1009
        throws IllegalFeatureException {
1010
        if (((DefaultFeature) feature).getStore() != this) {
1011
            throw new IllegalFeatureException(this.getName());
1012
        }
1013
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1014
        // fixFeatureType((DefaultFeatureType) feature.getType());
1015
    }
1016

    
1017
    private void exitEditingMode() {
1018
        if (commands != null) {
1019
            commands.clear();
1020
            commands = null;
1021
        }
1022

    
1023
        if (featureTypeManager != null) {
1024
            featureTypeManager.dispose();
1025
            featureTypeManager = null;
1026

    
1027
        }
1028

    
1029
        // TODO implementar un dispose para estos dos
1030
        featureManager = null;
1031
        spatialManager = null;
1032

    
1033
        featureCount = null;
1034

    
1035
        mode = MODE_QUERY;
1036
        hasStrongChanges = true; // Lo deja a true por si las moscas
1037
        hasInserts = true;
1038
    }
1039

    
1040
    @Override
1041
    synchronized public void edit() throws DataException {
1042
        edit(MODE_FULLEDIT);
1043
    }
1044

    
1045
    @Override
1046
    synchronized public void edit(int mode) throws DataException {
1047
        LOG.debug("Starting editing in mode: {}", mode);
1048
        try {
1049
            if (this.mode != MODE_QUERY) {
1050
                throw new AlreadyEditingException(this.getName());
1051
            }
1052
            if (!this.provider.supportsAppendMode()) {
1053
                mode = MODE_FULLEDIT;
1054
            }
1055
            switch (mode) {
1056
            case MODE_QUERY:
1057
                throw new IllegalStateException(this.getName());
1058

    
1059
            case MODE_FULLEDIT:
1060
                if (!this.transforms.isEmpty()) {
1061
                    throw new IllegalStateException(this.getName());
1062
                }
1063
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1064
                invalidateIndexes();
1065
                featureManager =
1066
                    new FeatureManager(new MemoryExpansionAdapter());
1067
                featureTypeManager =
1068
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
1069
                spatialManager =
1070
                    new SpatialManager(this, provider.getEnvelope());
1071

    
1072
                commands =
1073
                    new DefaultFeatureCommandsStack(this, featureManager,
1074
                        spatialManager, featureTypeManager);
1075
                this.mode = MODE_FULLEDIT;
1076
                hasStrongChanges = false;
1077
                hasInserts = false;
1078
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1079
                break;
1080
            case MODE_APPEND:
1081
                if (!this.transforms.isEmpty()) {
1082
                    throw new IllegalStateException(this.getName());
1083
                }
1084
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1085
                invalidateIndexes();
1086
                this.provider.beginAppend();
1087
                this.mode = MODE_APPEND;
1088
                hasInserts = false;
1089
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
1090
                break;
1091
            }
1092
        } catch (Exception e) {
1093
            throw new StoreEditException(e, this.getName());
1094
        }
1095
    }
1096

    
1097
    private void invalidateIndexes() {
1098
        setIndexesValidStatus(false);
1099
    }
1100

    
1101
    private void setIndexesValidStatus(boolean valid) {
1102
        FeatureIndexes theIndexes = getIndexes();
1103
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1104
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1105
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1106
            FeatureIndex index = (FeatureIndex) iterator.next();
1107
            if (index instanceof FeatureIndexProviderServices) {
1108
                FeatureIndexProviderServices indexServices =
1109
                    (FeatureIndexProviderServices) index;
1110
                indexServices.setValid(valid);
1111
            }
1112
        }
1113
    }
1114

    
1115
    private void updateIndexes() throws FeatureIndexException {
1116
        FeatureIndexes theIndexes = getIndexes();
1117
        LOG.debug("Refilling indexes: {}", theIndexes);
1118
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1119
            FeatureIndex index = (FeatureIndex) iterator.next();
1120
            if (index instanceof FeatureIndexProviderServices) {
1121
                FeatureIndexProviderServices indexServices =
1122
                    (FeatureIndexProviderServices) index;
1123
                indexServices.fill(true, null);
1124
            }
1125
        }
1126
    }
1127

    
1128
    private void waitForIndexes() {
1129
        FeatureIndexes theIndexes = getIndexes();
1130
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1131
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1132
            FeatureIndex index = (FeatureIndex) iterator.next();
1133
            if (index instanceof FeatureIndexProviderServices) {
1134
                FeatureIndexProviderServices indexServices =
1135
                    (FeatureIndexProviderServices) index;
1136
                indexServices.waitForIndex();
1137
            }
1138
        }
1139
    }
1140

    
1141
    private void disposeIndexes() {
1142
        FeatureIndexes theIndexes = getIndexes();
1143
        LOG.debug("Disposing indexes: {}", theIndexes);
1144
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1145
            FeatureIndex index = (FeatureIndex) iterator.next();
1146
            if (index instanceof FeatureIndexProviderServices) {
1147
                FeatureIndexProviderServices indexServices =
1148
                    (FeatureIndexProviderServices) index;
1149
                indexServices.dispose();
1150
            }
1151
        }
1152
    }
1153

    
1154
    @Override
1155
    public boolean isEditing() {
1156
        return mode == MODE_FULLEDIT;
1157
    }
1158

    
1159
    @Override
1160
    public boolean isAppending() {
1161
        return mode == MODE_APPEND;
1162
    }
1163

    
1164
    @Override
1165
    synchronized public void update(EditableFeatureType type)
1166
        throws DataException {
1167
        try {
1168
            checkInEditingMode();
1169
            if (type == null) {
1170
                throw new NullFeatureTypeException(getName());
1171
            }
1172
            // FIXME: Comprobar que es un featureType aceptable.
1173
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1174
            newVersionOfUpdate();
1175

    
1176
            FeatureType oldt = type.getSource().getCopy();
1177
            FeatureType newt = type.getCopy();
1178
            commands.update(newt, oldt);
1179

    
1180
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
1181
                hasStrongChanges = true;
1182
            }
1183
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1184
        } catch (Exception e) {
1185
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1186
        }
1187
    }
1188

    
1189
    @Override
1190
    public void delete(Feature feature) throws DataException {
1191
        this.commands.delete(feature);
1192
    }
1193

    
1194
    synchronized public void doDelete(Feature feature) throws DataException {
1195
        try {
1196
            checkInEditingMode();
1197
            checkIsOwnFeature(feature);
1198
            if (feature instanceof EditableFeature) {
1199
                throw new StoreDeleteEditableFeatureException(getName());
1200
            }
1201
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1202

    
1203
            //Update the featureManager and the spatialManager
1204
            featureManager.delete(feature.getReference());
1205
            spatialManager.deleteFeature(feature);
1206

    
1207
            newVersionOfUpdate();
1208
            hasStrongChanges = true;
1209
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1210
        } catch (Exception e) {
1211
            throw new StoreDeleteFeatureException(e, this.getName());
1212
        }
1213
    }
1214

    
1215
    private static EditableFeature lastChangedFeature = null;
1216

    
1217
    @Override
1218
    public synchronized void insert(EditableFeature feature)
1219
        throws DataException {
1220
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1221
        try {
1222
            switch (mode) {
1223
            case MODE_QUERY:
1224
                throw new NeedEditingModeException(this.getName());
1225

    
1226
            case MODE_APPEND:
1227
                checkIsOwnFeature(feature);
1228
                if (feature.getSource() != null) {
1229
                    throw new NoNewFeatureInsertException(this.getName());
1230
                }
1231
                this.featureCount = null;
1232
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1233
                feature.validate(Feature.UPDATE);
1234
                provider.append(((DefaultEditableFeature) feature).getData());
1235
                hasStrongChanges = true;
1236
                hasInserts = true;
1237
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1238
                break;
1239

    
1240
            case MODE_FULLEDIT:
1241
                if (feature.getSource() != null) {
1242
                    throw new NoNewFeatureInsertException(this.getName());
1243
                }
1244
                commands.insert(feature);
1245
            }
1246
        } catch (Exception e) {
1247
            throw new StoreInsertFeatureException(e, this.getName());
1248
        }
1249
    }
1250

    
1251
    synchronized public void doInsert(EditableFeature feature)
1252
        throws DataException {
1253
        checkIsOwnFeature(feature);
1254

    
1255
        waitForIndexes();
1256

    
1257
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1258
        newVersionOfUpdate();
1259
        if ((lastChangedFeature == null)
1260
            || (lastChangedFeature.getSource() != feature.getSource())) {
1261
            lastChangedFeature = feature;
1262
            feature.validate(Feature.UPDATE);
1263
            lastChangedFeature = null;
1264
        }
1265
        //Update the featureManager and the spatialManager
1266
        ((DefaultEditableFeature) feature).setInserted(true);
1267
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1268

    
1269

    
1270
        featureManager.add(newFeature);
1271
        spatialManager.insertFeature(newFeature);
1272

    
1273
        hasStrongChanges = true;
1274
        hasInserts = true;
1275
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1276
    }
1277

    
1278
    @Override
1279
    public void update(EditableFeature feature)
1280
    throws DataException {
1281
        if ((feature).getSource() == null) {
1282
            insert(feature);
1283
            return;
1284
        }
1285
        commands.update(feature, feature.getSource());
1286
    }
1287

    
1288
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1289
        throws DataException {
1290
        try {
1291
            checkInEditingMode();
1292
            checkIsOwnFeature(feature);
1293
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1294
            newVersionOfUpdate();
1295
            if ((lastChangedFeature == null)
1296
                || (lastChangedFeature.getSource() != feature.getSource())) {
1297
                lastChangedFeature = feature;
1298
                feature.validate(Feature.UPDATE);
1299
                lastChangedFeature = null;
1300
            }
1301

    
1302
            //Update the featureManager and the spatialManager
1303
            Feature newf = feature.getNotEditableCopy();
1304
            featureManager.update(newf, oldFeature);
1305
            spatialManager.updateFeature(newf, oldFeature);
1306

    
1307
            hasStrongChanges = true;
1308
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1309
        } catch (Exception e) {
1310
            throw new StoreUpdateFeatureException(e, this.getName());
1311
        }
1312
    }
1313

    
1314
    @Override
1315
    synchronized public void redo() throws RedoException {
1316
        Command redo = commands.getNextRedoCommand();
1317
        try {
1318
            checkInEditingMode();
1319
        } catch (NeedEditingModeException ex) {
1320
            throw new RedoException(redo, ex);
1321
        }
1322
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1323
        newVersionOfUpdate();
1324
        commands.redo();
1325
        hasStrongChanges = true;
1326
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1327
    }
1328

    
1329
    @Override
1330
    synchronized public void undo() throws UndoException {
1331
        Command undo = commands.getNextUndoCommand();
1332
        try {
1333
            checkInEditingMode();
1334
        } catch (NeedEditingModeException ex) {
1335
            throw new UndoException(undo, ex);
1336
        }
1337
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1338
        newVersionOfUpdate();
1339
        commands.undo();
1340
        hasStrongChanges = true;
1341
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1342
    }
1343

    
1344
    @Override
1345
    public List getRedoInfos() {
1346
        if (isEditing() && (commands != null)) {
1347
            return commands.getRedoInfos();
1348
        } else {
1349
            return null;
1350
        }
1351
    }
1352

    
1353
    @Override
1354
    public List getUndoInfos() {
1355
        if (isEditing() && (commands != null)) {
1356
            return commands.getUndoInfos();
1357
        } else {
1358
            return null;
1359
        }
1360
    }
1361

    
1362
    public synchronized FeatureCommandsStack getCommandsStack()
1363
        throws DataException {
1364
        checkInEditingMode();
1365
        return commands;
1366
    }
1367

    
1368
    @Override
1369
    synchronized public void cancelEditing() throws DataException {
1370
        spatialManager.cancelModifies();
1371
        try {
1372
            checkInEditingMode();
1373

    
1374
            boolean clearSelection = this.hasStrongChanges;
1375
            if (this.selection instanceof FeatureReferenceSelection) {
1376
                clearSelection = this.hasInserts;
1377
            }
1378
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1379
            exitEditingMode();
1380
            if (clearSelection) {
1381
                ((FeatureSelection) this.getSelection()).deselectAll();
1382
            }
1383
            updateIndexes();
1384
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1385
        } catch (Exception e) {
1386
            throw new StoreCancelEditingException(e, this.getName());
1387
        }
1388
    }
1389

    
1390
    @Override
1391
    synchronized public void finishEditing() throws DataException {
1392
        LOG.debug("finish editing of mode: {}", mode);
1393
        try {
1394

    
1395
            /*
1396
             * Selection needs to be cleared when editing stops
1397
             * to prevent conflicts with selection remaining from
1398
             * editing mode.
1399
             */
1400
//            ((FeatureSelection) this.getSelection()).deselectAll();
1401

    
1402
            switch (mode) {
1403
            case MODE_QUERY:
1404
                throw new NeedEditingModeException(this.getName());
1405

    
1406
            case MODE_APPEND:
1407
                ((FeatureSelection) this.getSelection()).deselectAll();
1408
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1409
                provider.endAppend();
1410
                exitEditingMode();
1411
                updateIndexes();
1412
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1413
                break;
1414

    
1415
            case MODE_FULLEDIT:
1416
                if (hasStrongChanges && !this.allowWrite()) {
1417
                    throw new WriteNotAllowedException(getName());
1418
                }
1419

    
1420
                if(featureManager.isSelectionCompromised()) {
1421
                    ((FeatureSelection) this.getSelection()).deselectAll();
1422
                };
1423

    
1424
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1425
                if (hasStrongChanges) {
1426
                    validateFeatures(Feature.FINISH_EDITING);
1427

    
1428
                    /*
1429
                     * This will throw a PerformEditingExceptionif the provider
1430
                     * does not accept the changes (for example, an invalid field name)
1431
                     */
1432
                    provider.performChanges(featureManager.getDeleted(),
1433
                        featureManager.getInserted(),
1434
                        featureManager.getUpdated(),
1435
                        featureTypeManager.getFeatureTypesChanged());
1436
                }
1437
                exitEditingMode();
1438
                updateIndexes();
1439
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1440
                break;
1441
            }
1442
        } catch (PerformEditingException pee) {
1443
            throw new WriteException(provider.getSourceId().toString(), pee);
1444
        } catch (Exception e) {
1445
            throw new FinishEditingException(e);
1446
        }
1447
    }
1448

    
1449
    /**
1450
     * Save changes in the provider without leaving the edit mode.
1451
     * Do not call observers to communicate a change of ediding mode.
1452
     * The operation's history is eliminated to prevent inconsistencies
1453
     * in the data.
1454
     *
1455
     * @throws DataException
1456
     */
1457
    @Override
1458
    synchronized public void commitChanges() throws DataException {
1459
      LOG.debug("commitChanges of mode: {}", mode);
1460
      if( !canCommitChanges() ) {
1461
              throw new WriteNotAllowedException(getName());
1462
      }
1463
      try {
1464
        switch (mode) {
1465
        case MODE_QUERY:
1466
          throw new NeedEditingModeException(this.getName());
1467

    
1468
        case MODE_APPEND:
1469
          this.provider.endAppend();
1470
          exitEditingMode();
1471
          invalidateIndexes();
1472
          this.provider.beginAppend();
1473
          hasInserts = false;
1474
          break;
1475

    
1476
        case MODE_FULLEDIT:
1477
          if (hasStrongChanges && !this.allowWrite()) {
1478
            throw new WriteNotAllowedException(getName());
1479
          }
1480
          if (hasStrongChanges) {
1481
            validateFeatures(Feature.FINISH_EDITING);
1482
            provider.performChanges(featureManager.getDeleted(),
1483
              featureManager.getInserted(),
1484
              featureManager.getUpdated(),
1485
              featureTypeManager.getFeatureTypesChanged());
1486
          }
1487
          invalidateIndexes();
1488
          featureManager =
1489
            new FeatureManager(new MemoryExpansionAdapter());
1490
          featureTypeManager =
1491
            new FeatureTypeManager(this, new MemoryExpansionAdapter());
1492
          spatialManager =
1493
            new SpatialManager(this, provider.getEnvelope());
1494

    
1495
          commands =
1496
            new DefaultFeatureCommandsStack(this, featureManager,
1497
              spatialManager, featureTypeManager);
1498
          featureCount = null;
1499
          hasStrongChanges = false;
1500
          hasInserts = false;
1501
          break;
1502
        }
1503
      } catch (Exception e) {
1504
        throw new FinishEditingException(e);
1505
      }
1506
    }
1507

    
1508
    @Override
1509
    synchronized public boolean canCommitChanges() throws DataException {
1510
        if ( !this.allowWrite()) {
1511
                return false;
1512
        }
1513
            switch (mode) {
1514
            default:
1515
        case MODE_QUERY:
1516
                return false;
1517

    
1518
        case MODE_APPEND:
1519
                return true;
1520

    
1521
        case MODE_FULLEDIT:
1522
            List types = this.getFeatureTypes();
1523
            for( int i=0; i<types.size(); i++ ) {
1524
                    Object type = types.get(i);
1525
                    if( type instanceof DefaultEditableFeatureType ) {
1526
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1527
                                    return false;
1528
                            }
1529
                    }
1530
            }
1531
            return true;
1532
            }
1533
    }
1534

    
1535
    @Override
1536
    public void beginEditingGroup(String description)
1537
        throws NeedEditingModeException {
1538
        checkInEditingMode();
1539
        commands.startComplex(description);
1540
    }
1541

    
1542
    @Override
1543
    public void endEditingGroup() throws NeedEditingModeException {
1544
        checkInEditingMode();
1545
        commands.endComplex();
1546
    }
1547

    
1548
    @Override
1549
    public boolean isAppendModeSupported() {
1550
        return this.provider.supportsAppendMode();
1551
    }
1552

    
1553
    @Override
1554
    public void export(DataServerExplorer explorer, String provider,
1555
        NewFeatureStoreParameters params) throws DataException {
1556

    
1557
        if (this.getFeatureTypes().size() != 1) {
1558
            throw new NotYetImplemented(
1559
                "export whith more than one type not yet implemented");
1560
        }
1561
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1562
        FeatureStore target = null;
1563
        FeatureSet features = null;
1564
        DisposableIterator iterator = null;
1565
        try {
1566
            FeatureType type = this.getDefaultFeatureType();
1567
            if ((params.getDefaultFeatureType() == null)
1568
                || (params.getDefaultFeatureType().size() == 0)) {
1569
                params.setDefaultFeatureType(type.getEditable());
1570

    
1571
            }
1572
            explorer.add(provider, params, true);
1573

    
1574
            DataManager manager = DALLocator.getDataManager();
1575
            target = (FeatureStore) manager.openStore(provider, params);
1576
            FeatureType targetType = target.getDefaultFeatureType();
1577

    
1578
            target.edit(MODE_APPEND);
1579
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1580
            if (featureSelection.getSize() > 0) {
1581
                features = this.getFeatureSelection();
1582
            } else {
1583
                if ((pk != null) && (pk.length > 0)) {
1584
                    FeatureQuery query = createFeatureQuery();
1585
                    for (int i = 0; i < pk.length; i++) {
1586
                        query.getOrder().add(pk[i].getName(), true);
1587
                    }
1588
                    features = this.getFeatureSet(query);
1589
                } else {
1590
                    features = this.getFeatureSet();
1591
                }
1592
            }
1593
            iterator = features.fastIterator();
1594
            while (iterator.hasNext()) {
1595
                DefaultFeature feature = (DefaultFeature) iterator.next();
1596
                target.insert(target.createNewFeature(targetType, feature));
1597
            }
1598
            target.finishEditing();
1599
            target.dispose();
1600
        } catch (Exception e) {
1601
            throw new DataExportException(e, params.toString());
1602
        } finally {
1603
            dispose(iterator);
1604
            dispose(features);
1605
            dispose(target);
1606
        }
1607
    }
1608

    
1609
    //
1610
    // ====================================================================
1611
    // Obtencion de datos
1612
    // getDataCollection, getFeatureCollection
1613
    //
1614

    
1615
    @Override
1616
    public DataSet getDataSet() throws DataException {
1617
        checkNotInAppendMode();
1618
        FeatureQuery query =
1619
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1620
        return new DefaultFeatureSet(this, query);
1621
    }
1622

    
1623
    @Override
1624
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1625
        checkNotInAppendMode();
1626
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1627
    }
1628

    
1629
    @Override
1630
    public void getDataSet(Observer observer) throws DataException {
1631
        checkNotInAppendMode();
1632
        this.getFeatureSet(null, observer);
1633
    }
1634

    
1635
    @Override
1636
    public void getDataSet(DataQuery dataQuery, Observer observer)
1637
        throws DataException {
1638
        checkNotInAppendMode();
1639
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1640
    }
1641

    
1642
    @Override
1643
    public FeatureSet getFeatureSet() throws DataException {
1644
        return this.getFeatureSet((FeatureQuery)null);
1645
    }
1646

    
1647
    @Override
1648
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1649
        throws DataException {
1650
        checkNotInAppendMode();
1651
        if( featureQuery==null ) {
1652
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1653
        }
1654
        return new DefaultFeatureSet(this, featureQuery);
1655
    }
1656

    
1657
    @Override
1658
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1659
        try {
1660
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1661
            return pager.asList();
1662
        } catch (BaseException ex) {
1663
            throw new RuntimeException("Can't create the list of features.", ex);
1664
        }
1665
    }
1666

    
1667
    @Override
1668
    public List<Feature> getFeatures() {
1669
        return this.getFeatures(null, 500);
1670
    }
1671

    
1672
    @Override
1673
    public void accept(Visitor visitor) throws BaseException {
1674
        FeatureSet set = getFeatureSet();
1675
        try {
1676
            set.accept(visitor);
1677
        } finally {
1678
            set.dispose();
1679
        }
1680
    }
1681

    
1682
    @Override
1683
    public void accept(Visitor visitor, DataQuery dataQuery)
1684
        throws BaseException {
1685
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1686
        try {
1687
            set.accept(visitor);
1688
        } finally {
1689
            set.dispose();
1690
        }
1691
    }
1692

    
1693
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1694
        throws DataException {
1695
        DefaultFeatureType fType =
1696
            (DefaultFeatureType) this.getFeatureType(featureQuery
1697
                .getFeatureTypeId());
1698
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1699
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1700
        }
1701
        return fType;
1702
    }
1703

    
1704
    @Override
1705
    public void getFeatureSet(Observer observer) throws DataException {
1706
        checkNotInAppendMode();
1707
        this.getFeatureSet(null, observer);
1708
    }
1709

    
1710
    @Override
1711
    public void getFeatureSet(FeatureQuery query, Observer observer)
1712
        throws DataException {
1713
        class LoadInBackGround implements Runnable {
1714

    
1715
            private final FeatureStore store;
1716
            private final FeatureQuery query;
1717
            private final Observer observer;
1718

    
1719
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1720
                Observer observer) {
1721
                this.store = store;
1722
                this.query = query;
1723
                this.observer = observer;
1724
            }
1725

    
1726
            void notify(FeatureStoreNotification theNotification) {
1727
                observer.update(store, theNotification);
1728
            }
1729

    
1730
            @Override
1731
            public void run() {
1732
                FeatureSet set = null;
1733
                try {
1734
                    set = store.getFeatureSet(query);
1735
                    notify(new DefaultFeatureStoreNotification(store,
1736
                        FeatureStoreNotification.LOAD_FINISHED, set));
1737
                } catch (Exception e) {
1738
                    notify(new DefaultFeatureStoreNotification(store,
1739
                        FeatureStoreNotification.LOAD_FINISHED, e));
1740
                } finally {
1741
                    dispose(set);
1742
                }
1743
            }
1744
        }
1745

    
1746
        checkNotInAppendMode();
1747
        if (query == null) {
1748
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1749
        }
1750
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1751
        Thread thread = new Thread(task, "Load Feature Set in background");
1752
        thread.start();
1753
    }
1754

    
1755
    @Override
1756
    public Feature getFeatureByReference(FeatureReference reference)
1757
        throws DataException {
1758
        checkNotInAppendMode();
1759
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1760
        FeatureType featureType;
1761
        if (ref.getFeatureTypeId() == null) {
1762
            featureType = this.getDefaultFeatureType();
1763
        } else {
1764
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1765
        }
1766
        return this.getFeatureByReference(reference, featureType);
1767
    }
1768

    
1769
    @Override
1770
    public Feature getFeatureByReference(FeatureReference reference,
1771
        FeatureType featureType) throws DataException {
1772
        checkNotInAppendMode();
1773
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1774
        if (this.mode == MODE_FULLEDIT) {
1775
            Feature f = featureManager.get(reference, this, featureType);
1776
            if (f != null) {
1777
                return f;
1778
            }
1779
        }
1780

    
1781
        FeatureType sourceFeatureType = featureType;
1782
        if (!this.transforms.isEmpty()) {
1783
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1784
        }
1785
        // TODO comprobar que el id es de este store
1786

    
1787
        DefaultFeature feature =
1788
            new DefaultFeature(this,
1789
                this.provider.getFeatureProviderByReference(
1790
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1791

    
1792
        if (!this.transforms.isEmpty()) {
1793
            return this.transforms.applyTransform(feature, featureType);
1794
        }
1795
        return feature;
1796
    }
1797

    
1798
    //
1799
    // ====================================================================
1800
    // Gestion de features
1801
    //
1802

    
1803
    private FeatureType fixFeatureType(DefaultFeatureType type)
1804
        throws DataException {
1805
        FeatureType original = this.getDefaultFeatureType();
1806

    
1807
        if ((type == null) || type.equals(original)) {
1808
            return original;
1809
        } else {
1810
            if (!type.isSubtypeOf(original)) {
1811
                Iterator iter = this.getFeatureTypes().iterator();
1812
                FeatureType tmpType;
1813
                boolean found = false;
1814
                while (iter.hasNext()) {
1815
                    tmpType = (FeatureType) iter.next();
1816
                    if (type.equals(tmpType)) {
1817
                        return type;
1818

    
1819
                    } else
1820
                        if (type.isSubtypeOf(tmpType)) {
1821
                            found = true;
1822
                            original = tmpType;
1823
                            break;
1824
                        }
1825

    
1826
                }
1827
                if (!found) {
1828
                    throw new IllegalFeatureTypeException(getName());
1829
                }
1830
            }
1831
        }
1832

    
1833
        // Checks that type has all fields of pk
1834
        // else add the missing attributes at the end.
1835
        if (!original.hasOID()) {
1836
            // Gets original pk attributes
1837
            DefaultEditableFeatureType edOriginal =
1838
                (DefaultEditableFeatureType) original.getEditable();
1839
            FeatureAttributeDescriptor orgAttr;
1840
            Iterator edOriginalIter = edOriginal.iterator();
1841
            while (edOriginalIter.hasNext()) {
1842
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1843
                if (!orgAttr.isPrimaryKey()) {
1844
                    edOriginalIter.remove();
1845
                }
1846
            }
1847

    
1848
            // Checks if all pk attributes are in type
1849
            Iterator typeIterator;
1850
            edOriginalIter = edOriginal.iterator();
1851
            FeatureAttributeDescriptor attr;
1852
            while (edOriginalIter.hasNext()) {
1853
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1854
                typeIterator = type.iterator();
1855
                while (typeIterator.hasNext()) {
1856
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1857
                    if (attr.getName().equals(orgAttr.getName())) {
1858
                        edOriginalIter.remove();
1859
                        break;
1860
                    }
1861
                }
1862
            }
1863

    
1864
            // add missing pk attributes if any
1865
            if (edOriginal.size() > 0) {
1866
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1867
                DefaultEditableFeatureType edType =
1868
                    (DefaultEditableFeatureType) original.getEditable();
1869
                edType.clear();
1870
                edType.addAll(type);
1871
                edType.addAll(edOriginal);
1872
                if (!isEditable) {
1873
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1874
                }
1875
            }
1876

    
1877
        }
1878

    
1879
        return type;
1880
    }
1881

    
1882
    @Override
1883
    public void validateFeatures(int mode) throws DataException {
1884
        FeatureSet collection = null;
1885
        DisposableIterator iter = null;
1886
        try {
1887
            checkNotInAppendMode();
1888
            collection = this.getFeatureSet();
1889
            iter = collection.fastIterator();
1890
            long previousVersionOfUpdate = currentVersionOfUpdate();
1891
            while (iter.hasNext()) {
1892
                ((DefaultFeature) iter.next()).validate(mode);
1893
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1894
                    throw new ConcurrentDataModificationException(getName());
1895
                }
1896
            }
1897
        } catch (Exception e) {
1898
            throw new ValidateFeaturesException(e, getName());
1899
        } finally {
1900
            dispose(iter);
1901
            dispose(collection);
1902
        }
1903
    }
1904

    
1905
    @Override
1906
    public FeatureType getDefaultFeatureType() throws DataException {
1907
        try {
1908

    
1909
            if (isEditing()) {
1910
                FeatureType auxFeatureType =
1911
                    featureTypeManager.getType(defaultFeatureType.getId());
1912
                if (auxFeatureType != null) {
1913
                    return avoidEditable(auxFeatureType);
1914
                }
1915
            }
1916
            FeatureType type = this.transforms.getDefaultFeatureType();
1917
            if (type != null) {
1918
                return avoidEditable(type);
1919
            }
1920

    
1921
            return avoidEditable(defaultFeatureType);
1922

    
1923
        } catch (Exception e) {
1924
            throw new GetFeatureTypeException(e, getName());
1925
        }
1926
    }
1927

    
1928
    private FeatureType avoidEditable(FeatureType ft) {
1929
        if (ft instanceof EditableFeatureType) {
1930
            return ((EditableFeatureType) ft).getNotEditableCopy();
1931
        } else {
1932
            return ft;
1933
        }
1934
    }
1935

    
1936
    @Override
1937
    public FeatureType getFeatureType(String featureTypeId)
1938
        throws DataException {
1939
        if (featureTypeId == null) {
1940
            return this.getDefaultFeatureType();
1941
        }
1942
        try {
1943
            if (isEditing()) {
1944
                FeatureType auxFeatureType =
1945
                    featureTypeManager.getType(featureTypeId);
1946
                if (auxFeatureType != null) {
1947
                    return auxFeatureType;
1948
                }
1949
            }
1950
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1951
            if (type != null) {
1952
                return type;
1953
            }
1954
            Iterator iter = this.featureTypes.iterator();
1955
            while (iter.hasNext()) {
1956
                type = (FeatureType) iter.next();
1957
                if (type.getId().equals(featureTypeId)) {
1958
                    return type;
1959
                }
1960
            }
1961
            return null;
1962
        } catch (Exception e) {
1963
            throw new GetFeatureTypeException(e, getName());
1964
        }
1965
    }
1966

    
1967
    public FeatureType getProviderDefaultFeatureType() {
1968
        return defaultFeatureType;
1969
    }
1970

    
1971
    @Override
1972
    public List getFeatureTypes() throws DataException {
1973
        try {
1974
            List types;
1975
            if (isEditing()) {
1976
                types = new ArrayList();
1977
                Iterator it = featureTypes.iterator();
1978
                while (it.hasNext()) {
1979
                    FeatureType type = (FeatureType) it.next();
1980
                    FeatureType typeaux =
1981
                        featureTypeManager.getType(type.getId());
1982
                    if (typeaux != null) {
1983
                        types.add(typeaux);
1984
                    } else {
1985
                        types.add(type);
1986
                    }
1987
                }
1988
                it = featureTypeManager.newsIterator();
1989
                while (it.hasNext()) {
1990
                    FeatureType type = (FeatureType) it.next();
1991
                    types.add(type);
1992
                }
1993
            } else {
1994
                types = this.transforms.getFeatureTypes();
1995
                if (types == null) {
1996
                    types = featureTypes;
1997
                }
1998
            }
1999
            return Collections.unmodifiableList(types);
2000
        } catch (Exception e) {
2001
            throw new GetFeatureTypeException(e, getName());
2002
        }
2003
    }
2004

    
2005
    public List getProviderFeatureTypes() throws DataException {
2006
        return Collections.unmodifiableList(this.featureTypes);
2007
    }
2008

    
2009
    @Override
2010
    public Feature createFeature(FeatureProvider data) throws DataException {
2011
        DefaultFeature feature = new DefaultFeature(this, data);
2012
        return feature;
2013
    }
2014

    
2015
    public Feature createFeature(FeatureProvider data, FeatureType type)
2016
        throws DataException {
2017
        // FIXME: falta por implementar
2018
        // Comprobar si es un subtipo del feature de data
2019
        // y construir un feature usando el subtipo.
2020
        // Probablemente requiera generar una copia del data.
2021
        throw new NotYetImplemented();
2022
    }
2023

    
2024
    @Override
2025
    public EditableFeature createNewFeature(FeatureType type,
2026
        Feature defaultValues) throws DataException {
2027
        try {
2028
            FeatureProvider data = createNewFeatureProvider(type);
2029
            DefaultEditableFeature feature =
2030
                new DefaultEditableFeature(this, data);
2031
            feature.initializeValues(defaultValues);
2032
            data.setNew(true);
2033

    
2034
            return feature;
2035
        } catch (Exception e) {
2036
            throw new CreateFeatureException(e, getName());
2037
        }
2038
    }
2039

    
2040
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2041
        throws DataException {
2042
        type = this.fixFeatureType((DefaultFeatureType) type);
2043
        FeatureProvider data = this.provider.createFeatureProvider(type);
2044
        data.setNew(true);
2045
        if (type.hasOID() && (data.getOID() == null)) {
2046
            data.setOID(this.provider.createNewOID());
2047
        } else {
2048
            data.setOID(this.getTemporalOID());
2049
        }
2050
        return data;
2051

    
2052
    }
2053

    
2054
    @Override
2055
    public EditableFeature createNewFeature(FeatureType type,
2056
        boolean defaultValues) throws DataException {
2057
        try {
2058
            FeatureProvider data = createNewFeatureProvider(type);
2059
            DefaultEditableFeature feature =
2060
                new DefaultEditableFeature(this, data);
2061
            if (defaultValues) {
2062
                feature.initializeValues();
2063
            }
2064
            return feature;
2065
        } catch (Exception e) {
2066
            throw new CreateFeatureException(e, getName());
2067
        }
2068
    }
2069

    
2070
    @Override
2071
    public EditableFeature createNewFeature(boolean defaultValues)
2072
        throws DataException {
2073
        return this.createNewFeature(this.getDefaultFeatureType(),
2074
            defaultValues);
2075
    }
2076

    
2077
    @Override
2078
    public EditableFeature createNewFeature() throws DataException {
2079
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2080
    }
2081

    
2082
    @Override
2083
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2084
        FeatureType ft = this.getDefaultFeatureType();
2085
        EditableFeature f = this.createNewFeature(ft, false);
2086
                for( FeatureAttributeDescriptor desc : ft ) {
2087
                        try {
2088
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2089
                        } catch(Throwable th) {
2090
                                // Ignore
2091
                        }
2092
                }
2093
        return f;
2094
    }
2095

    
2096
    @Override
2097
    public EditableFeatureType createFeatureType() {
2098
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
2099
        return ftype;
2100
    }
2101

    
2102
    @Override
2103
    public EditableFeatureType createFeatureType(String id) {
2104
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
2105
        return ftype;
2106
    }
2107

    
2108
    //
2109
    // ====================================================================
2110
    // Index related methods
2111
    //
2112

    
2113
    @Override
2114
    public FeatureIndexes getIndexes() {
2115
        return this.indexes;
2116
    }
2117

    
2118
    @Override
2119
    public FeatureIndex createIndex(FeatureType featureType,
2120
        String attributeName, String indexName) throws DataException {
2121
        return createIndex(null, featureType, attributeName, indexName);
2122
    }
2123

    
2124
    @Override
2125
    public FeatureIndex createIndex(String indexTypeName,
2126
        FeatureType featureType, String attributeName, String indexName)
2127
        throws DataException {
2128

    
2129
        return createIndex(indexTypeName, featureType, attributeName,
2130
            indexName, false, null);
2131
    }
2132

    
2133
    @Override
2134
    public FeatureIndex createIndex(FeatureType featureType,
2135
        String attributeName, String indexName, Observer observer)
2136
        throws DataException {
2137
        return createIndex(null, featureType, attributeName, indexName,
2138
            observer);
2139
    }
2140

    
2141
    @Override
2142
    public FeatureIndex createIndex(String indexTypeName,
2143
        FeatureType featureType, String attributeName, String indexName,
2144
        final Observer observer) throws DataException {
2145

    
2146
        return createIndex(indexTypeName, featureType, attributeName,
2147
            indexName, true, observer);
2148
    }
2149

    
2150
    private FeatureIndex createIndex(String indexTypeName,
2151
        FeatureType featureType, String attributeName, String indexName,
2152
        boolean background, final Observer observer) throws DataException {
2153

    
2154
        checkNotInAppendMode();
2155
        FeatureIndexProviderServices index;
2156
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2157
                featureType, indexName,
2158
                featureType.getAttributeDescriptor(attributeName));
2159

    
2160
        try {
2161
            index.fill(background, observer);
2162
        } catch (FeatureIndexException e) {
2163
            throw new InitializeException(index.getName(), e);
2164
        }
2165

    
2166
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2167
        return index;
2168
    }
2169

    
2170
    //
2171
    // ====================================================================
2172
    // Transforms related methods
2173
    //
2174

    
2175
    @Override
2176
    public FeatureStoreTransforms getTransforms() {
2177
        return this.transforms;
2178
    }
2179

    
2180
    @Override
2181
    public FeatureQuery createFeatureQuery() {
2182
        return new DefaultFeatureQuery();
2183
    }
2184

    
2185
    @Override
2186
    public DataQuery createQuery() {
2187
        return createFeatureQuery();
2188
    }
2189

    
2190
    //
2191
    // ====================================================================
2192
    // UndoRedo related methods
2193
    //
2194

    
2195
    @Override
2196
    public boolean canRedo() {
2197
        return commands.canRedo();
2198
    }
2199

    
2200
    @Override
2201
    public boolean canUndo() {
2202
        return commands.canUndo();
2203
    }
2204

    
2205
    @Override
2206
    public void redo(int num) throws RedoException {
2207
        for (int i = 0; i < num; i++) {
2208
            redo();
2209
        }
2210
    }
2211

    
2212
    @Override
2213
    public void undo(int num) throws UndoException {
2214
        for (int i = 0; i < num; i++) {
2215
            undo();
2216
        }
2217
    }
2218

    
2219
    //
2220
    // ====================================================================
2221
    // Metadata related methods
2222
    //
2223

    
2224
    @Override
2225
    public Object getMetadataID() {
2226
        return this.provider.getSourceId();
2227
    }
2228

    
2229
    @Override
2230
    public void delegate(DynObject dynObject) {
2231
        this.metadata.delegate(dynObject);
2232
    }
2233

    
2234
    @Override
2235
    public DynClass getDynClass() {
2236
        return this.metadata.getDynClass();
2237
    }
2238

    
2239
    @Override
2240
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2241
                if( this.transforms.hasDynValue(name) ) {
2242
                        return this.transforms.getDynValue(name);
2243
                }
2244
                if (this.metadata.hasDynValue(name)) {
2245
                        return this.metadata.getDynValue(name);
2246
                }
2247
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2248
                        return this.provider.getProviderName();
2249
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2250
                        return this.provider.getSourceId();
2251
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2252
                        try {
2253
                                return this.getDefaultFeatureType();
2254
                        } catch (DataException e) {
2255
                                return null;
2256
                        }
2257
                }
2258
                return this.metadata.getDynValue(name);
2259
        }
2260

    
2261
    @Override
2262
    public boolean hasDynValue(String name) {
2263
                if( this.transforms.hasDynValue(name) ) {
2264
                        return true;
2265
                }
2266
        return this.metadata.hasDynValue(name);
2267
    }
2268

    
2269
    @Override
2270
    public void implement(DynClass dynClass) {
2271
        this.metadata.implement(dynClass);
2272
    }
2273

    
2274
    @Override
2275
    public Object invokeDynMethod(String name, Object[] args)
2276
        throws DynMethodException {
2277
        return this.metadata.invokeDynMethod(this, name, args);
2278
    }
2279

    
2280
    @Override
2281
    public Object invokeDynMethod(int code, Object[] args)
2282
        throws DynMethodException {
2283
        return this.metadata.invokeDynMethod(this, code, args);
2284
    }
2285

    
2286
    @Override
2287
    public void setDynValue(String name, Object value)
2288
        throws DynFieldNotFoundException {
2289
                if( this.transforms.hasDynValue(name) ) {
2290
                        this.transforms.setDynValue(name, value);
2291
                        return;
2292
                }
2293
        this.metadata.setDynValue(name, value);
2294

    
2295
    }
2296

    
2297
    /*
2298
     * (non-Javadoc)
2299
     *
2300
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2301
     */
2302
    @Override
2303
    public Set getMetadataChildren() {
2304
        return this.metadataChildren;
2305
    }
2306

    
2307
    /*
2308
     * (non-Javadoc)
2309
     *
2310
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2311
     */
2312
    @Override
2313
    public String getMetadataName() {
2314
        return this.provider.getProviderName();
2315
    }
2316

    
2317
    public FeatureTypeManager getFeatureTypeManager() {
2318
        return this.featureTypeManager;
2319
    }
2320

    
2321
    @Override
2322
    public long getFeatureCount() throws DataException {
2323
        if (featureCount == null) {
2324
            featureCount = this.provider.getFeatureCount();
2325
        }
2326
        if (this.isEditing()) {
2327
            if(this.isAppending()) {
2328
                try{
2329
                    throw new IllegalStateException();
2330
                } catch(IllegalStateException e) {
2331
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND");
2332
                    e.printStackTrace();
2333
                }
2334
                return -1;
2335
            } else {
2336
                return featureCount
2337
                    + this.featureManager.getDeltaSize();
2338
            }
2339
        }
2340
        return featureCount;
2341
    }
2342

    
2343
    private Long getTemporalOID() {
2344
        return this.temporalOid++;
2345
    }
2346

    
2347
    @Override
2348
    public FeatureType getProviderFeatureType(String featureTypeId) {
2349
        if (featureTypeId == null) {
2350
            return this.defaultFeatureType;
2351
        }
2352
        FeatureType type;
2353
        Iterator iter = this.featureTypes.iterator();
2354
        while (iter.hasNext()) {
2355
            type = (FeatureType) iter.next();
2356
            if (type.getId().equals(featureTypeId)) {
2357
                return type;
2358
            }
2359
        }
2360
        return null;
2361
    }
2362

    
2363
    @Override
2364
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2365
        return ((DefaultFeature) feature).getData();
2366
    }
2367

    
2368
    @Override
2369
    public DataStore getStore() {
2370
        return this;
2371
    }
2372

    
2373
    @Override
2374
    public FeatureStore getFeatureStore() {
2375
        return this;
2376
    }
2377

    
2378
    @Override
2379
    public void createCache(String name, DynObject parameters)
2380
        throws DataException {
2381
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2382
        if (cache == null) {
2383
            throw new CreateException("FeaureCacheProvider", null);
2384
        }
2385
        cache.apply(this, provider);
2386
        provider = cache;
2387

    
2388
        featureCount = null;
2389
    }
2390

    
2391
    @Override
2392
    public FeatureCache getCache() {
2393
        return cache;
2394
    }
2395

    
2396
    @Override
2397
    public void clear() {
2398
        if (metadata != null) {
2399
            metadata.clear();
2400
        }
2401
    }
2402

    
2403
    @Override
2404
    public String getName() {
2405
        if( this.provider != null ) {
2406
            return this.provider.getName();
2407
        }
2408
        if( this.parameters instanceof HasAFile ) {
2409
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2410
        }
2411
        return "unknow";
2412
    }
2413

    
2414
    @Override
2415
    public String getFullName() {
2416
        try {
2417
            if( this.provider!=null ) {
2418
                return this.provider.getFullName();
2419
            }
2420
            if( this.parameters instanceof HasAFile ) {
2421
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2422
            }
2423
            return null;
2424
        } catch(Throwable th) {
2425
            return null;
2426
        }
2427
    }
2428

    
2429
    @Override
2430
    public String getProviderName() {
2431
        if( this.provider!=null ) {
2432
            return this.provider.getProviderName();
2433
        }
2434
        if( this.parameters != null ) {
2435
            return this.parameters.getDataStoreName();
2436
        }
2437
        return null;
2438
        
2439
    }
2440

    
2441
    @Override
2442
    public boolean isKnownEnvelope() {
2443
        return this.provider.isKnownEnvelope();
2444
    }
2445

    
2446
    @Override
2447
    public boolean hasRetrievedFeaturesLimit() {
2448
        return this.provider.hasRetrievedFeaturesLimit();
2449
    }
2450

    
2451
    @Override
2452
    public int getRetrievedFeaturesLimit() {
2453
        return this.provider.getRetrievedFeaturesLimit();
2454
    }
2455

    
2456
    @Override
2457
    public Interval getInterval() {
2458
        if( this.timeSupport!=null ) {
2459
            return this.timeSupport.getInterval();
2460
        }
2461
        return this.provider.getInterval();
2462
    }
2463

    
2464
    @Override
2465
    public Collection getTimes() {
2466
        if( this.timeSupport!=null ) {
2467
            return this.timeSupport.getTimes();
2468
        }
2469
        return this.provider.getTimes();
2470
    }
2471

    
2472
    @Override
2473
    public Collection getTimes(Interval interval) {
2474
        if( this.timeSupport!=null ) {
2475
            return this.timeSupport.getTimes(interval);
2476
        }
2477
        return this.provider.getTimes(interval);
2478
    }
2479

    
2480
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2481
        FeatureAttributeDescriptor attr;
2482
        DefaultFeatureType ft;
2483
        try {
2484
            ft = (DefaultFeatureType) this.getDefaultFeatureType();
2485
        } catch (DataException ex) {
2486
            throw new RuntimeException("Can't add time support, can't get the default feature type.", ex);
2487
        }
2488
        attr = ft.getAttributeDescriptor(timeSupport.getAttributeName());
2489
        if( attr != null ) {
2490
            throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2491
        }
2492
        attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2493
        if( attr != null ) {
2494
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2495
        }
2496
        DefaultEditableFeatureAttributeDescriptor attr2 = new DefaultEditableFeatureAttributeDescriptor();
2497
        attr2.setDataType(timeSupport.getDataType());
2498
        attr2.setIsTime(true);
2499
        attr2.setFeatureAttributeEmulator(timeSupport);
2500
        ft.add(attr2);
2501

    
2502
        this.timeSupport = timeSupport;
2503
    }
2504

    
2505
    @Override
2506
    public Object clone() throws CloneNotSupportedException {
2507

    
2508
        DataStoreParameters dsp = getParameters();
2509

    
2510
        DefaultFeatureStore cloned_store = null;
2511

    
2512
        try {
2513
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2514
                openStore(this.getProviderName(), dsp);
2515
            if (transforms != null) {
2516
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2517
                cloned_store.transforms.setStoreForClone(cloned_store);
2518
            }
2519
        } catch (Exception e) {
2520
            throw new CloneException(e);
2521
        }
2522
        return cloned_store;
2523

    
2524
    }
2525

    
2526
    @Override
2527
    public Feature getFeature(DynObject dynobject) {
2528
        if (dynobject instanceof DynObjectFeatureFacade){
2529
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2530
            return f;
2531
        }
2532
        return null;
2533
    }
2534

    
2535
    @Override
2536
    public Iterator iterator() {
2537
        try {
2538
            return this.getFeatureSet().fastIterator();
2539
        } catch (DataException ex) {
2540
            throw new RuntimeException(ex);
2541
        }
2542
    }
2543

    
2544
    @Override
2545
    public ExpressionEvaluator createExpression() {
2546
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2547
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2548
        }
2549
        return new SQLBuilderBase();
2550
    }
2551

    
2552

    
2553
    public FeatureSet features() throws DataException {
2554
        // This is to avoid jython to create a property with this name
2555
        // to access method getFeatures.
2556
        return this.getFeatureSet();
2557
    }
2558

    
2559
    @Override
2560
    public DataStoreProviderFactory getProviderFactory() {
2561
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2562
        return factory;
2563
    }
2564

    
2565
    @Override
2566
    public void useCache(String providerName, DynObject parameters) throws DataException {
2567
        throw new UnsupportedOperationException();
2568
    }
2569
    
2570
    @Override
2571
    public boolean isBroken() {
2572
        return this.state.isBroken();
2573
    }
2574

    
2575
    @Override
2576
    public Throwable getBreakingsCause() {
2577
            return this.state.getBreakingsCause();
2578
    }
2579
}