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 @ 43628

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

    
40
import org.apache.commons.io.FilenameUtils;
41
import org.apache.commons.lang3.StringUtils;
42
import org.cresques.cts.IProjection;
43

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

    
161
import org.slf4j.Logger;
162
import org.slf4j.LoggerFactory;
163

    
164
public class DefaultFeatureStore extends AbstractDisposable implements
165
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
166

    
167
    private static final Logger LOG = LoggerFactory
168
        .getLogger(DefaultFeatureStore.class);
169

    
170
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
171

    
172
    private DataStoreParameters parameters = null;
173
    private FeatureSelection selection;
174
    private FeatureLocks locks;
175

    
176
    private DelegateWeakReferencingObservable delegateObservable =
177
        new DelegateWeakReferencingObservable(this);
178

    
179
    private FeatureCommandsStack commands;
180
    private FeatureTypeManager featureTypeManager;
181
    private FeatureManager featureManager;
182
    private SpatialManager spatialManager;
183

    
184
    private FeatureType defaultFeatureType = null;
185
    private List featureTypes = new ArrayList();
186

    
187
    private int mode = MODE_QUERY;
188
    private long versionOfUpdate = 0;
189
    private boolean hasStrongChanges = true;
190
    private boolean hasInserts = true;
191

    
192
    private DefaultDataManager dataManager = null;
193

    
194
    private FeatureStoreProvider provider = null;
195

    
196
    private DefaultFeatureIndexes indexes;
197

    
198
    private DefaultFeatureStoreTransforms transforms;
199

    
200
    DelegatedDynObject metadata;
201

    
202
    private Set metadataChildren;
203

    
204
    private Long featureCount = null;
205

    
206
    private long temporalOid = 0;
207

    
208
    private FeatureCacheProvider cache;
209

    
210
    StateInformation state;
211

    
212
    FeatureStoreTimeSupport timeSupport;
213

    
214

    
215
    private class StateInformation extends HashMap<Object, Object> {
216

    
217
        private static final long serialVersionUID = 4109026189635185666L;
218

    
219
        private boolean broken;
220
        private Throwable breakingsCause;
221

    
222
        public StateInformation() {
223
            this.clear();
224
        }
225

    
226
        @Override
227
        public void clear() {
228
            this.broken = false;
229
            this.breakingsCause = null;
230
            super.clear();
231
        }
232

    
233
        public boolean isBroken() {
234
            return this.broken;
235
        }
236

    
237
        public void broken() {
238
            this.broken = true;
239
        }
240

    
241
        public Throwable getBreakingsCause() {
242
            return this.breakingsCause;
243
        }
244

    
245
        public void setBreakingsCause(Throwable cause) {
246
            if( this.breakingsCause==null ) {
247
                this.breakingsCause = cause;
248
            }
249
            this.broken = true;
250
        }
251
    }
252

    
253

    
254

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

    
264
    public DefaultFeatureStore() {
265
        this.state = new StateInformation();
266
    }
267

    
268
    @Override
269
    public void intialize(DataManager dataManager,
270
        DataStoreParameters parameters) throws InitializeException {
271

    
272
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
273

    
274
        this.metadata = (DelegatedDynObject) dynManager.createDynObject(
275
            FeatureStore.METADATA_DEFINITION_NAME,
276
            MetadataManager.METADATA_NAMESPACE
277
        );
278

    
279
        this.dataManager = (DefaultDataManager) dataManager;
280

    
281
        this.parameters = parameters;
282
        this.transforms = new DefaultFeatureStoreTransforms(this);
283
        try {
284
            indexes = new DefaultFeatureIndexes(this);
285
        } catch (DataException e) {
286
            throw new InitializeException(e);
287
        }
288

    
289
    }
290

    
291
    @Override
292
    public void setProvider(org.gvsig.fmap.dal.DataStoreProvider provider) {
293
        this.provider = (FeatureStoreProvider) provider;
294
        this.delegate((DynObject) provider);
295
        this.metadataChildren = new HashSet();
296
        this.metadataChildren.add(provider);
297
    }
298

    
299
    @Override
300
    public DataStoreParameters getParameters() {
301
        return parameters;
302
    }
303

    
304
    public int getMode() {
305
        return this.mode;
306
    }
307

    
308
    @Override
309
    public DataManager getManager() {
310
        return this.dataManager;
311
    }
312

    
313
    @Override
314
    public Iterator getChildren() {
315
        return this.provider.getChilds();
316
    }
317

    
318
    @Override
319
    public FeatureStoreProvider getProvider() {
320
        return this.provider;
321
    }
322

    
323
    public FeatureManager getFeatureManager() {
324
        return this.featureManager;
325
    }
326

    
327
    @Override
328
    public void setFeatureTypes(List types, FeatureType defaultType) {
329
        this.featureTypes = types;
330
        this.defaultFeatureType = defaultType;
331
    }
332

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

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

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

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

    
403
        if (this.featureTypeManager != null) {
404
            this.featureTypeManager.dispose();
405
            this.featureTypeManager = null;
406
        }
407

    
408
        this.featureManager = null;
409
        this.spatialManager = null;
410

    
411
        this.parameters = null;
412
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
413
        if (delegateObservable != null) {
414
            this.delegateObservable.deleteObservers();
415
            this.delegateObservable = null;
416
        }
417
    }
418

    
419
    @Override
420
    public boolean allowWrite() {
421
        SimpleIdentityManager identityManager = ToolsLocator.getIdentityManager();
422
        if( ! identityManager.getCurrentIdentity().isAuthorized(DataManager.WRITE_STORE_AUTHORIZATION,this.getParameters(), this.getName()) ) {
423
            return false;
424
        }
425
        return this.provider.allowWrite();
426
    }
427

    
428
    @Override
429
    public boolean canWriteGeometry(int geometryType) throws DataException {
430
        return this.provider.canWriteGeometry(geometryType, 0);
431
    }
432

    
433
    @Override
434
    public DataServerExplorer getExplorer() throws ReadException,
435
        ValidateDataParametersException {
436
        if( this.state.isBroken() ) {
437
            try {
438
                return this.provider.getExplorer();
439
            } catch(Throwable th) {
440
                return null;
441
            }
442
        } else {
443
            return this.provider.getExplorer();
444
        }
445
    }
446

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

    
459
    @Override
460
    public Envelope getEnvelope() throws DataException {
461
        if (this.mode == MODE_FULLEDIT) {
462
                // Just in case another thread tries to write in the store
463
                synchronized (this) {
464
                        return this.spatialManager.getEnvelope();
465
                        }
466
        }
467
        if (hasDynValue(DataStore.METADATA_ENVELOPE)){
468
            return (Envelope)getDynValue(DataStore.METADATA_ENVELOPE);
469
        }
470
        return this.provider.getEnvelope();
471
    }
472

    
473
    /**
474
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
475
     */
476
    @Override
477
    public IProjection getSRSDefaultGeometry() throws DataException {
478
        return this.getDefaultFeatureType().getDefaultSRS();
479
    }
480

    
481
    @Override
482
    public FeatureSelection createDefaultFeatureSelection()
483
        throws DataException {
484
        return new DefaultFeatureSelection(this);
485
    }
486

    
487
    @Override
488
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
489
        throws DataException {
490
        if (type.hasOID()) {
491
            return new DefaultFeatureProvider(type,
492
                this.provider.createNewOID());
493
        }
494
        return new DefaultFeatureProvider(type);
495
    }
496

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

    
532
        }
533

    
534
        if (evaluatedAttr.isEmpty()) {
535
            evaluatedAttr = null;
536
        }
537

    
538
        state.set("evaluatedAttributes", evaluatedAttr);
539
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
540

    
541
    }
542

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

    
581
    private void load(StateInformation state) {
582
        this.featureTypes = new ArrayList();
583
        this.defaultFeatureType = null;
584
        this.featureCount = null;
585

    
586
        DataStoreParameters params = (DataStoreParameters) state.get("parameters");
587
        try {
588
            intialize(dataManager, params);
589
        } catch(Throwable th) {
590
            state.setBreakingsCause(th);
591
        }
592

    
593
        try {
594
            DataStoreProvider prov = dataManager.createProvider(
595
                getStoreProviderServices(),
596
                params
597
            );
598
            setProvider(prov);
599
        } catch(Throwable th) {
600
            state.setBreakingsCause(th);
601
        }
602

    
603
        try {
604
            selection = (FeatureSelection) state.get("selection");
605
        } catch(Throwable th) {
606
            state.setBreakingsCause(th);
607
        }
608

    
609
        try {
610
            this.transforms = (DefaultFeatureStoreTransforms) state.get("transforms");
611
            this.transforms.setFeatureStore(this);
612
            for( FeatureStoreTransform transform : this.transforms ) {
613
                try {
614
                    transform.setUp();
615
                } catch(Throwable th) {
616
                    state.setBreakingsCause(th);
617
                }
618
            }
619
        } catch(Throwable th) {
620
            state.setBreakingsCause(th);
621
        }
622

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

    
654
                    }
655

    
656
            }
657
        } catch(Throwable th) {
658
            state.setBreakingsCause(th);
659
        }
660

    
661

    
662
        try {
663
            String defaultFeatureTypeId = (String) state.get("defaultFeatureTypeId");
664
            FeatureType ftype;
665

    
666
            if (defaultFeatureType == null ||
667
                    defaultFeatureType.getId() == null ||
668
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
669

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

    
689
        LOG.info("load() broken:{}, {}, {}.",
690
                new Object[] { state.isBroken(), this.getProviderName(), params }
691
        );
692
    }
693

    
694
        public DataStoreProviderServices getStoreProviderServices() {
695
                return this;
696
        }
697

    
698
    public static void registerPersistenceDefinition() {
699
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
700
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
701
            DynStruct definition =
702
                manager.addDefinition(DefaultFeatureStore.class,
703
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
704
                        + " Persistent definition", null, null);
705
            definition.addDynFieldString("dataStoreName").setMandatory(true)
706
                .setPersistent(true);
707

    
708
            definition.addDynFieldObject("parameters")
709
                .setClassOfValue(DynObject.class).setMandatory(true)
710
                .setPersistent(true);
711

    
712
            definition.addDynFieldObject("selection")
713
                .setClassOfValue(FeatureSelection.class).setMandatory(false)
714
                .setPersistent(true);
715

    
716
            definition.addDynFieldObject("transforms")
717
                .setClassOfValue(DefaultFeatureStoreTransforms.class)
718
                .setMandatory(true).setPersistent(true);
719

    
720
            definition.addDynFieldMap("evaluatedAttributes")
721
                .setClassOfItems(List.class) // List<DefaultFeatureAttributeDescriptor>
722
                .setMandatory(false).setPersistent(true);
723

    
724
            definition.addDynFieldString("defaultFeatureTypeId")
725
                .setMandatory(true).setPersistent(true);
726
        }
727
    }
728

    
729
    public static void registerMetadataDefinition() throws MetadataException {
730
        MetadataManager manager = MetadataLocator.getMetadataManager();
731
        if (manager.getDefinition(FeatureStore.METADATA_DEFINITION_NAME) == null) {
732
            DynStruct metadataDefinition =
733
                manager.addDefinition(FeatureStore.METADATA_DEFINITION_NAME, null);
734
            metadataDefinition.extend(manager
735
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
736
        }
737
    }
738

    
739
    //
740
    // ====================================================================
741
    // Gestion de la seleccion
742
    //
743

    
744
    @Override
745
    public void setSelection(DataSet selection) throws DataException {
746
        this.setSelection((FeatureSet) selection);
747
    }
748

    
749
    @Override
750
    public DataSet createSelection() throws DataException {
751
        return createFeatureSelection();
752
    }
753

    
754
    @Override
755
    public DataSet getSelection() throws DataException {
756
        return this.getFeatureSelection();
757
    }
758

    
759
    @Override
760
    public void setSelection(FeatureSet selection) throws DataException {
761
        setSelection(selection, true);
762
    }
763

    
764
    public void setSelection(FeatureSet selection, boolean undoable)
765
        throws DataException {
766
        if (selection == null) {
767
            if (undoable) {
768
                throw new SelectionNotAllowedException(getName());
769
            }
770

    
771
        } else {
772
            if (selection.equals(this.selection)) {
773
                return;
774
            }
775
            if (!selection.isFromStore(this)) {
776
                throw new SelectionNotAllowedException(getName());
777
            }
778
        }
779

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

    
818
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
819
    }
820

    
821
    @Override
822
    public FeatureSelection createFeatureSelection() throws DataException {
823
        return this.provider.createFeatureSelection();
824
    }
825

    
826
    @Override
827
    public FeatureSelection getFeatureSelection() throws DataException {
828
        if (selection == null) {
829
            this.selection = createFeatureSelection();
830
            this.selection.addObserver(this);
831
        }
832
        return selection;
833
    }
834

    
835
    //
836
    // ====================================================================
837
    // Gestion de notificaciones
838
    //
839

    
840
    @Override
841
    public void notifyChange(FeatureStoreNotification storeNotification) {
842
        try {
843
            delegateObservable.notifyObservers(storeNotification);
844
        } catch (Throwable ex) {
845
            LOG.warn("Problems notifying changes in the store '"+this.getName()+" ("+storeNotification.getType()+").",ex);
846
        }
847
    }
848

    
849
    @Override
850
    public void notifyChange(String notification) {
851
        if (delegateObservable != null) {
852
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
853
        }
854

    
855
    }
856

    
857
    @Override
858
    public void notifyChange(String notification, FeatureProvider data) {
859
        Feature f = null;
860
        try {
861
            f = createFeature(data);
862
        } catch (Throwable ex) {
863
            LOG.warn("Problems creating a feature to notifying changes in the store '"+this.getName()+" ("+notification+").",ex);
864
        }
865
        notifyChange(notification, f);
866
    }
867

    
868
    public void notifyChange(String notification, Feature feature) {
869
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
870
            feature));
871
    }
872

    
873
    public void notifyChange(String notification, Command command) {
874
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
875
            command));
876
    }
877

    
878
    public void notifyChange(String notification, EditableFeatureType type) {
879
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
880
            type));
881
    }
882

    
883
    @Override
884
    public void notifyChange(String notification, Resource resource) {
885
        notifyChange(new DefaultFeatureStoreNotification(this,
886
            DataStoreNotification.RESOURCE_CHANGED));
887
    }
888

    
889
    //
890
    // ====================================================================
891
    // Gestion de bloqueos
892
    //
893

    
894
    @Override
895
    public boolean isLocksSupported() {
896
        return this.provider.isLocksSupported();
897
    }
898

    
899
    @Override
900
    public FeatureLocks getLocks() throws DataException {
901
        if (!this.provider.isLocksSupported()) {
902
            LOG.warn("Locks not supported");
903
            return null;
904
        }
905
        if (locks == null) {
906
            this.locks = this.provider.createFeatureLocks();
907
        }
908
        return locks;
909
    }
910

    
911
    //
912
    // ====================================================================
913
    // Interface Observable
914
    //
915

    
916
    @Override
917
    public void disableNotifications() {
918
        this.delegateObservable.disableNotifications();
919

    
920
    }
921

    
922
    @Override
923
    public void enableNotifications() {
924
        this.delegateObservable.enableNotifications();
925
    }
926

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

    
931
    }
932

    
933
    @Override
934
    public void endComplexNotification() {
935
        this.delegateObservable.endComplexNotification();
936

    
937
    }
938

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

    
946
    @Override
947
    public void deleteObserver(Observer observer) {
948
        if (delegateObservable != null) {
949
            this.delegateObservable.deleteObserver(observer);
950
        }
951
    }
952

    
953
    @Override
954
    public void deleteObservers() {
955
        this.delegateObservable.deleteObservers();
956

    
957
    }
958

    
959
    //
960
    // ====================================================================
961
    // Interface Observer
962
    //
963
    // Usado para observar:
964
    // - su seleccion
965
    // - sus bloqueos
966
    // - sus recursos
967
    //
968

    
969
    @Override
970
    public void update(Observable observable, Object notification) {
971
        if (observable instanceof FeatureSet) {
972
            if (observable == this.selection) {
973
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
974
            } else if (observable == this.locks) {
975
                this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
976
            }
977

    
978
        } else if (observable instanceof FeatureStoreProvider) {
979
            if (observable == this.provider) {
980

    
981
            }
982
        } else if (observable instanceof FeatureReferenceSelection) {
983
            if(notification instanceof String){
984
                    this.notifyChange((String)notification);
985
            }
986
        }
987
    }
988

    
989
    //
990
    // ====================================================================
991
    // Edicion
992
    //
993

    
994
    private void newVersionOfUpdate() {
995
        this.versionOfUpdate++;
996
    }
997

    
998
    private long currentVersionOfUpdate() {
999
        return this.versionOfUpdate;
1000
    }
1001

    
1002
    private void checkInEditingMode() throws NeedEditingModeException {
1003
        if (mode != MODE_FULLEDIT) {
1004
            throw new NeedEditingModeException(this.getName());
1005
        }
1006
    }
1007

    
1008
    private void checkNotInAppendMode() throws IllegalStateException {
1009
        if (mode == MODE_APPEND) {
1010
                        throw new IllegalStateException("Error: store "
1011
                                        + this.getFullName() + " is in append mode");
1012
        }
1013
    }
1014

    
1015
    private void checkIsOwnFeature(Feature feature)
1016
        throws IllegalFeatureException {
1017
        if (((DefaultFeature) feature).getStore() != this) {
1018
            throw new IllegalFeatureException(this.getName());
1019
        }
1020
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
1021
        // fixFeatureType((DefaultFeatureType) feature.getType());
1022
    }
1023

    
1024
    private void exitEditingMode() {
1025
        if (commands != null) {
1026
            commands.clear();
1027
            commands = null;
1028
        }
1029

    
1030
        if (featureTypeManager != null) {
1031
            featureTypeManager.dispose();
1032
            featureTypeManager = null;
1033

    
1034
        }
1035

    
1036
        // TODO implementar un dispose para estos dos
1037
        featureManager = null;
1038
        spatialManager = null;
1039

    
1040
        featureCount = null;
1041

    
1042
        mode = MODE_QUERY;
1043
        hasStrongChanges = true; // Lo deja a true por si las moscas
1044
        hasInserts = true;
1045
    }
1046

    
1047
    @Override
1048
    synchronized public void edit() throws DataException {
1049
        edit(MODE_FULLEDIT);
1050
    }
1051

    
1052
    @Override
1053
    synchronized public void edit(int mode) throws DataException {
1054
        LOG.debug("Starting editing in mode: {}", mode);
1055
        try {
1056
            if (this.mode != MODE_QUERY) {
1057
                throw new AlreadyEditingException(this.getName());
1058
            }
1059
            if (!this.provider.supportsAppendMode()) {
1060
                mode = MODE_FULLEDIT;
1061
            }
1062
            switch (mode) {
1063
            case MODE_QUERY:
1064
                throw new IllegalStateException(this.getName());
1065

    
1066
            case MODE_FULLEDIT:
1067
                if (!this.transforms.isEmpty()) {
1068
                    throw new IllegalStateException(this.getName());
1069
                }
1070
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
1071
                invalidateIndexes();
1072
                featureManager =
1073
                    new FeatureManager(new MemoryExpansionAdapter());
1074
                featureTypeManager =
1075
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
1076
                spatialManager =
1077
                    new SpatialManager(this, provider.getEnvelope());
1078

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

    
1104
    private void invalidateIndexes() {
1105
        setIndexesValidStatus(false);
1106
    }
1107

    
1108
    private void setIndexesValidStatus(boolean valid) {
1109
        FeatureIndexes theIndexes = getIndexes();
1110
        LOG.debug("Setting the store indexes to valid status {}: {}", (valid
1111
            ? Boolean.TRUE : Boolean.FALSE), theIndexes);
1112
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1113
            FeatureIndex index = (FeatureIndex) iterator.next();
1114
            if (index instanceof FeatureIndexProviderServices) {
1115
                FeatureIndexProviderServices indexServices =
1116
                    (FeatureIndexProviderServices) index;
1117
                indexServices.setValid(valid);
1118
            }
1119
        }
1120
    }
1121

    
1122
    private void updateIndexes() throws FeatureIndexException {
1123
        FeatureIndexes theIndexes = getIndexes();
1124
        LOG.debug("Refilling indexes: {}", theIndexes);
1125
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1126
            FeatureIndex index = (FeatureIndex) iterator.next();
1127
            if (index instanceof FeatureIndexProviderServices) {
1128
                FeatureIndexProviderServices indexServices =
1129
                    (FeatureIndexProviderServices) index;
1130
                indexServices.fill(true, null);
1131
            }
1132
        }
1133
    }
1134

    
1135
    private void waitForIndexes() {
1136
        FeatureIndexes theIndexes = getIndexes();
1137
        LOG.debug("Waiting for indexes to finish filling: {}", theIndexes);
1138
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1139
            FeatureIndex index = (FeatureIndex) iterator.next();
1140
            if (index instanceof FeatureIndexProviderServices) {
1141
                FeatureIndexProviderServices indexServices =
1142
                    (FeatureIndexProviderServices) index;
1143
                indexServices.waitForIndex();
1144
            }
1145
        }
1146
    }
1147

    
1148
    private void disposeIndexes() {
1149
        FeatureIndexes theIndexes = getIndexes();
1150
        LOG.debug("Disposing indexes: {}", theIndexes);
1151
        if( theIndexes==null ) {
1152
            return;
1153
        }
1154
        for (Iterator iterator = theIndexes.iterator(); iterator.hasNext();) {
1155
            FeatureIndex index = (FeatureIndex) iterator.next();
1156
            if (index instanceof FeatureIndexProviderServices) {
1157
                FeatureIndexProviderServices indexServices =
1158
                    (FeatureIndexProviderServices) index;
1159
                indexServices.dispose();
1160
            }
1161
        }
1162
    }
1163

    
1164
    @Override
1165
    public boolean isEditing() {
1166
        return mode == MODE_FULLEDIT;
1167
    }
1168

    
1169
    @Override
1170
    public boolean isAppending() {
1171
        return mode == MODE_APPEND;
1172
    }
1173

    
1174
    @Override
1175
    synchronized public void update(EditableFeatureType type)
1176
        throws DataException {
1177
        try {
1178
            checkInEditingMode();
1179
            if (type == null) {
1180
                throw new NullFeatureTypeException(getName());
1181
            }
1182
            // FIXME: Comprobar que es un featureType aceptable.
1183
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
1184
            newVersionOfUpdate();
1185

    
1186
            FeatureType oldt = type.getSource().getCopy();
1187
            FeatureType newt = type.getCopy();
1188
            commands.update(newt, oldt);
1189

    
1190
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
1191
                hasStrongChanges = true;
1192
            }
1193
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
1194
        } catch (Exception e) {
1195
            throw new StoreUpdateFeatureTypeException(e, this.getName());
1196
        }
1197
    }
1198

    
1199
    @Override
1200
    public void delete(Feature feature) throws DataException {
1201
        this.commands.delete(feature);
1202
    }
1203

    
1204
    synchronized public void doDelete(Feature feature) throws DataException {
1205
        try {
1206
            checkInEditingMode();
1207
            checkIsOwnFeature(feature);
1208
            if (feature instanceof EditableFeature) {
1209
                throw new StoreDeleteEditableFeatureException(getName());
1210
            }
1211
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
1212

    
1213
            //Update the featureManager and the spatialManager
1214
            featureManager.delete(feature.getReference());
1215
            spatialManager.deleteFeature(feature);
1216

    
1217
            newVersionOfUpdate();
1218
            hasStrongChanges = true;
1219
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
1220
        } catch (Exception e) {
1221
            throw new StoreDeleteFeatureException(e, this.getName());
1222
        }
1223
    }
1224

    
1225
    private static EditableFeature lastChangedFeature = null;
1226

    
1227
    @Override
1228
    public synchronized void insert(EditableFeature feature)
1229
        throws DataException {
1230
        LOG.debug("In editing mode {}, insert feature: {}", mode, feature);
1231
        try {
1232
            switch (mode) {
1233
            case MODE_QUERY:
1234
                throw new NeedEditingModeException(this.getName());
1235

    
1236
            case MODE_APPEND:
1237
                checkIsOwnFeature(feature);
1238
                if (feature.getSource() != null) {
1239
                    throw new NoNewFeatureInsertException(this.getName());
1240
                }
1241
                this.featureCount = null;
1242
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1243
                feature.validate(Feature.UPDATE);
1244
                provider.append(((DefaultEditableFeature) feature).getData());
1245
                hasStrongChanges = true;
1246
                hasInserts = true;
1247
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1248
                break;
1249

    
1250
            case MODE_FULLEDIT:
1251
                if (feature.getSource() != null) {
1252
                    throw new NoNewFeatureInsertException(this.getName());
1253
                }
1254
                commands.insert(feature);
1255
            }
1256
        } catch (Exception e) {
1257
            throw new StoreInsertFeatureException(e, this.getName());
1258
        }
1259
    }
1260

    
1261
    synchronized public void doInsert(EditableFeature feature)
1262
        throws DataException {
1263
        checkIsOwnFeature(feature);
1264

    
1265
        waitForIndexes();
1266

    
1267
        notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
1268
        newVersionOfUpdate();
1269
        if ((lastChangedFeature == null)
1270
            || (lastChangedFeature.getSource() != feature.getSource())) {
1271
            lastChangedFeature = feature;
1272
            feature.validate(Feature.UPDATE);
1273
            lastChangedFeature = null;
1274
        }
1275
        //Update the featureManager and the spatialManager
1276
        ((DefaultEditableFeature) feature).setInserted(true);
1277
        DefaultFeature newFeature = (DefaultFeature) feature.getNotEditableCopy();
1278

    
1279

    
1280
        featureManager.add(newFeature);
1281
        spatialManager.insertFeature(newFeature);
1282

    
1283
        hasStrongChanges = true;
1284
        hasInserts = true;
1285
        notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
1286
    }
1287

    
1288
    @Override
1289
    public void update(EditableFeature feature)
1290
    throws DataException {
1291
        if ((feature).getSource() == null) {
1292
            insert(feature);
1293
            return;
1294
        }
1295
        commands.update(feature, feature.getSource());
1296
    }
1297

    
1298
    synchronized public void doUpdate(EditableFeature feature, Feature oldFeature)
1299
        throws DataException {
1300
        try {
1301
            checkInEditingMode();
1302
            checkIsOwnFeature(feature);
1303
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
1304
            newVersionOfUpdate();
1305
            if ((lastChangedFeature == null)
1306
                || (lastChangedFeature.getSource() != feature.getSource())) {
1307
                lastChangedFeature = feature;
1308
                feature.validate(Feature.UPDATE);
1309
                lastChangedFeature = null;
1310
            }
1311

    
1312
            //Update the featureManager and the spatialManager
1313
            Feature newf = feature.getNotEditableCopy();
1314
            featureManager.update(newf, oldFeature);
1315
            spatialManager.updateFeature(newf, oldFeature);
1316

    
1317
            hasStrongChanges = true;
1318
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
1319
        } catch (Exception e) {
1320
            throw new StoreUpdateFeatureException(e, this.getName());
1321
        }
1322
    }
1323

    
1324
    @Override
1325
    synchronized public void redo() throws RedoException {
1326
        Command redo = commands.getNextRedoCommand();
1327
        try {
1328
            checkInEditingMode();
1329
        } catch (NeedEditingModeException ex) {
1330
            throw new RedoException(redo, ex);
1331
        }
1332
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1333
        newVersionOfUpdate();
1334
        commands.redo();
1335
        hasStrongChanges = true;
1336
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1337
    }
1338

    
1339
    @Override
1340
    synchronized public void undo() throws UndoException {
1341
        Command undo = commands.getNextUndoCommand();
1342
        try {
1343
            checkInEditingMode();
1344
        } catch (NeedEditingModeException ex) {
1345
            throw new UndoException(undo, ex);
1346
        }
1347
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1348
        newVersionOfUpdate();
1349
        commands.undo();
1350
        hasStrongChanges = true;
1351
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1352
    }
1353

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

    
1363
    @Override
1364
    public List getUndoInfos() {
1365
        if (isEditing() && (commands != null)) {
1366
            return commands.getUndoInfos();
1367
        } else {
1368
            return null;
1369
        }
1370
    }
1371

    
1372
    public synchronized FeatureCommandsStack getCommandsStack()
1373
        throws DataException {
1374
        checkInEditingMode();
1375
        return commands;
1376
    }
1377

    
1378
    @Override
1379
    synchronized public void cancelEditing() throws DataException {
1380
        spatialManager.cancelModifies();
1381
        try {
1382
            switch (mode) {
1383
            case MODE_QUERY:
1384
                throw new NeedEditingModeException(this.getName());
1385

    
1386
            case MODE_APPEND:
1387
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1388
                provider.abortAppend();
1389
                exitEditingMode();
1390
                ((FeatureSelection) this.getSelection()).deselectAll();
1391
                updateIndexes();
1392
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1393

    
1394
            case MODE_FULLEDIT:
1395
                boolean clearSelection = this.hasStrongChanges;
1396
                if (this.selection instanceof FeatureReferenceSelection) {
1397
                    clearSelection = this.hasInserts;
1398
                }
1399
                notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1400
                exitEditingMode();
1401
                if (clearSelection) {
1402
                    ((FeatureSelection) this.getSelection()).deselectAll();
1403
                }
1404
                updateIndexes();
1405
                notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);   
1406
            }
1407
        } catch (Exception e) {
1408
            throw new StoreCancelEditingException(e, this.getName());
1409
        }
1410
    }
1411

    
1412
    @Override
1413
    synchronized public void finishEditing() throws DataException {
1414
        LOG.debug("finish editing of mode: {}", mode);
1415
        try {
1416

    
1417
            /*
1418
             * Selection needs to be cleared when editing stops
1419
             * to prevent conflicts with selection remaining from
1420
             * editing mode.
1421
             */
1422
//            ((FeatureSelection) this.getSelection()).deselectAll();
1423

    
1424
            switch (mode) {
1425
            case MODE_QUERY:
1426
                throw new NeedEditingModeException(this.getName());
1427

    
1428
            case MODE_APPEND:
1429
                if( selection!=null ) {
1430
                    selection = null;
1431
                }
1432
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1433
                provider.endAppend();
1434
                exitEditingMode();
1435
                updateIndexes();
1436
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1437
                break;
1438

    
1439
            case MODE_FULLEDIT:
1440
                if (hasStrongChanges && !this.allowWrite()) {
1441
                    throw new WriteNotAllowedException(getName());
1442
                }
1443
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1444
                    selection = null;
1445
                }
1446
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1447
                if (hasStrongChanges) {
1448
                    validateFeatures(Feature.FINISH_EDITING);
1449

    
1450
                    /*
1451
                     * This will throw a PerformEditingExceptionif the provider
1452
                     * does not accept the changes (for example, an invalid field name)
1453
                     */
1454
                    provider.performChanges(featureManager.getDeleted(),
1455
                        featureManager.getInserted(),
1456
                        featureManager.getUpdated(),
1457
                        featureTypeManager.getFeatureTypesChanged());
1458
                }
1459
                exitEditingMode();
1460
                updateIndexes();
1461
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1462
                break;
1463
            }
1464
        } catch (PerformEditingException pee) {
1465
            throw new WriteException(provider.getSourceId().toString(), pee);
1466
        } catch (Exception e) {
1467
            throw new FinishEditingException(e);
1468
        }
1469
    }
1470

    
1471
    /**
1472
     * Save changes in the provider without leaving the edit mode.
1473
     * Do not call observers to communicate a change of ediding mode.
1474
     * The operation's history is eliminated to prevent inconsistencies
1475
     * in the data.
1476
     *
1477
     * @throws DataException
1478
     */
1479
    @Override
1480
    synchronized public void commitChanges() throws DataException {
1481
      LOG.debug("commitChanges of mode: {}", mode);
1482
      if( !canCommitChanges() ) {
1483
              throw new WriteNotAllowedException(getName());
1484
      }
1485
      try {
1486
        switch (mode) {
1487
        case MODE_QUERY:
1488
          throw new NeedEditingModeException(this.getName());
1489

    
1490
        case MODE_APPEND:
1491
          this.provider.endAppend();
1492
          exitEditingMode();
1493
          invalidateIndexes();
1494
          this.provider.beginAppend();
1495
          hasInserts = false;
1496
          break;
1497

    
1498
        case MODE_FULLEDIT:
1499
          if (hasStrongChanges && !this.allowWrite()) {
1500
            throw new WriteNotAllowedException(getName());
1501
          }
1502
          if (hasStrongChanges) {
1503
            validateFeatures(Feature.FINISH_EDITING);
1504
            provider.performChanges(featureManager.getDeleted(),
1505
              featureManager.getInserted(),
1506
              featureManager.getUpdated(),
1507
              featureTypeManager.getFeatureTypesChanged());
1508
          }
1509
          invalidateIndexes();
1510
          featureManager =
1511
            new FeatureManager(new MemoryExpansionAdapter());
1512
          featureTypeManager =
1513
            new FeatureTypeManager(this, new MemoryExpansionAdapter());
1514
          spatialManager =
1515
            new SpatialManager(this, provider.getEnvelope());
1516

    
1517
          commands =
1518
            new DefaultFeatureCommandsStack(this, featureManager,
1519
              spatialManager, featureTypeManager);
1520
          featureCount = null;
1521
          hasStrongChanges = false;
1522
          hasInserts = false;
1523
          break;
1524
        }
1525
      } catch (Exception e) {
1526
        throw new FinishEditingException(e);
1527
      }
1528
    }
1529

    
1530
    @Override
1531
    synchronized public boolean canCommitChanges() throws DataException {
1532
        if ( !this.allowWrite()) {
1533
                return false;
1534
        }
1535
            switch (mode) {
1536
            default:
1537
        case MODE_QUERY:
1538
                return false;
1539

    
1540
        case MODE_APPEND:
1541
                return true;
1542

    
1543
        case MODE_FULLEDIT:
1544
            List types = this.getFeatureTypes();
1545
            for( int i=0; i<types.size(); i++ ) {
1546
                    Object type = types.get(i);
1547
                    if( type instanceof DefaultEditableFeatureType ) {
1548
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1549
                                    return false;
1550
                            }
1551
                    }
1552
            }
1553
            return true;
1554
            }
1555
    }
1556

    
1557
    @Override
1558
    public void beginEditingGroup(String description)
1559
        throws NeedEditingModeException {
1560
        checkInEditingMode();
1561
        commands.startComplex(description);
1562
    }
1563

    
1564
    @Override
1565
    public void endEditingGroup() throws NeedEditingModeException {
1566
        checkInEditingMode();
1567
        commands.endComplex();
1568
    }
1569

    
1570
    @Override
1571
    public boolean isAppendModeSupported() {
1572
        return this.provider.supportsAppendMode();
1573
    }
1574

    
1575
    @Override
1576
    public void export(DataServerExplorer explorer, String provider,
1577
        NewFeatureStoreParameters params) throws DataException {
1578

    
1579
        if (this.getFeatureTypes().size() != 1) {
1580
            throw new NotYetImplemented(
1581
                "export whith more than one type not yet implemented");
1582
        }
1583
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1584
        FeatureStore target = null;
1585
        FeatureSet features = null;
1586
        DisposableIterator iterator = null;
1587
        try {
1588
            FeatureType type = this.getDefaultFeatureType();
1589
            if ((params.getDefaultFeatureType() == null)
1590
                || (params.getDefaultFeatureType().size() == 0)) {
1591
                params.setDefaultFeatureType(type.getEditable());
1592

    
1593
            }
1594
            explorer.add(provider, params, true);
1595

    
1596
            DataManager manager = DALLocator.getDataManager();
1597
            target = (FeatureStore) manager.openStore(provider, params);
1598
            FeatureType targetType = target.getDefaultFeatureType();
1599

    
1600
            target.edit(MODE_APPEND);
1601
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1602
            if (featureSelection.getSize() > 0) {
1603
                features = this.getFeatureSelection();
1604
            } else {
1605
                if ((pk != null) && (pk.length > 0)) {
1606
                    FeatureQuery query = createFeatureQuery();
1607
                    for (int i = 0; i < pk.length; i++) {
1608
                        query.getOrder().add(pk[i].getName(), true);
1609
                    }
1610
                    features = this.getFeatureSet(query);
1611
                } else {
1612
                    features = this.getFeatureSet();
1613
                }
1614
            }
1615
            iterator = features.fastIterator();
1616
            while (iterator.hasNext()) {
1617
                DefaultFeature feature = (DefaultFeature) iterator.next();
1618
                target.insert(target.createNewFeature(targetType, feature));
1619
            }
1620
            target.finishEditing();
1621
            target.dispose();
1622
        } catch (Exception e) {
1623
            throw new DataExportException(e, params.toString());
1624
        } finally {
1625
            dispose(iterator);
1626
            dispose(features);
1627
            dispose(target);
1628
        }
1629
    }
1630

    
1631
    //
1632
    // ====================================================================
1633
    // Obtencion de datos
1634
    // getDataCollection, getFeatureCollection
1635
    //
1636

    
1637
    @Override
1638
    public DataSet getDataSet() throws DataException {
1639
        checkNotInAppendMode();
1640
        FeatureQuery query =
1641
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1642
        return new DefaultFeatureSet(this, query);
1643
    }
1644

    
1645
    @Override
1646
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1647
        checkNotInAppendMode();
1648
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1649
    }
1650

    
1651
    @Override
1652
    public void getDataSet(Observer observer) throws DataException {
1653
        checkNotInAppendMode();
1654
        this.getFeatureSet(null, observer);
1655
    }
1656

    
1657
    @Override
1658
    public void getDataSet(DataQuery dataQuery, Observer observer)
1659
        throws DataException {
1660
        checkNotInAppendMode();
1661
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1662
    }
1663

    
1664
    @Override
1665
    public FeatureSet getFeatureSet() throws DataException {
1666
        return this.getFeatureSet((FeatureQuery)null);
1667
    }
1668

    
1669
    @Override
1670
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1671
        throws DataException {
1672
        checkNotInAppendMode();
1673
        if( featureQuery==null ) {
1674
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1675
        }
1676
        return new DefaultFeatureSet(this, featureQuery);
1677
    }
1678

    
1679
    @Override
1680
    public FeatureSet getFeatureSet(String filter) throws DataException {
1681
        return this.getFeatureSet(filter, null, true);
1682
    }
1683

    
1684
    @Override
1685
    public FeatureSet getFeatureSet(String filter, String sortBy) throws DataException {
1686
        return this.getFeatureSet(filter, sortBy, true);
1687
    }
1688

    
1689
    @Override
1690
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1691
        FeatureQuery query = this.createFeatureQuery();
1692
        if( !StringUtils.isEmpty(filter) ) {
1693
            query.setFilter(filter);
1694
        }
1695
        if( !StringUtils.isEmpty(sortBy) ) {
1696
            query.getOrder().add(sortBy, asc);
1697
        }
1698
        return this.getFeatureSet(query);
1699
    }
1700
    
1701
    @Override
1702
    public List<Feature> getFeatures(String filter)  {
1703
        return this.getFeatures(filter, null, true);
1704
    }
1705

    
1706
    @Override
1707
    public List<Feature> getFeatures(String filter, String sortBy)  {
1708
        return this.getFeatures(filter, sortBy, true);
1709
    }
1710

    
1711
    @Override
1712
    public List<Feature> getFeatures(String filter, String sortBy, boolean asc)  {
1713
        FeatureQuery query = this.createFeatureQuery();
1714
        if( !StringUtils.isEmpty(filter) ) {
1715
            query.setFilter(filter);
1716
        }
1717
        if( !StringUtils.isEmpty(sortBy) ) {
1718
            query.getOrder().add(sortBy, asc);
1719
        }
1720
        return this.getFeatures(query, 100);
1721
    }
1722
    
1723
    @Override
1724
    public List<Feature> getFeatures(FeatureQuery query)  {
1725
        return this.getFeatures(query, 100);
1726
    }
1727
    
1728
    @Override
1729
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1730
        try {
1731
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1732
            return pager.asList();
1733
        } catch (BaseException ex) {
1734
            throw new RuntimeException("Can't create the list of features.", ex);
1735
        }
1736
    }
1737

    
1738
    @Override
1739
    public List<Feature> getFeatures() {
1740
        return this.getFeatures(null, 500);
1741
    }
1742

    
1743
    @Override
1744
    public Feature findFirst(String filter) throws DataException {
1745
        return this.findFirst(filter, null, true);
1746
    }
1747

    
1748
    @Override
1749
    public Feature findFirst(String filter, String sortBy) throws DataException {
1750
        return this.findFirst(filter, sortBy, true);
1751
    }
1752

    
1753
    @Override
1754
    public Feature findFirst(String filter, String sortBy, boolean asc) throws DataException {
1755
        FeatureSet set = this.getFeatureSet(filter, sortBy, asc);
1756
        if( set==null || set.isEmpty() ) {
1757
            return null;
1758
        }
1759
        DisposableIterator it = set.iterator();
1760
        Feature f = (Feature) it.next();
1761
        it.dispose();
1762
        return f;
1763
    }
1764
    
1765
    @Override
1766
    public void accept(Visitor visitor) throws BaseException {
1767
        FeatureSet set = getFeatureSet();
1768
        try {
1769
            set.accept(visitor);
1770
        } finally {
1771
            set.dispose();
1772
        }
1773
    }
1774

    
1775
    @Override
1776
    public void accept(Visitor visitor, DataQuery dataQuery)
1777
        throws BaseException {
1778
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1779
        try {
1780
            set.accept(visitor);
1781
        } finally {
1782
            set.dispose();
1783
        }
1784
    }
1785

    
1786
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1787
        throws DataException {
1788
        DefaultFeatureType fType =
1789
            (DefaultFeatureType) this.getFeatureType(featureQuery
1790
                .getFeatureTypeId());
1791
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1792
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1793
        }
1794
        return fType;
1795
    }
1796

    
1797
    @Override
1798
    public void getFeatureSet(Observer observer) throws DataException {
1799
        checkNotInAppendMode();
1800
        this.getFeatureSet(null, observer);
1801
    }
1802

    
1803
    @Override
1804
    public void getFeatureSet(FeatureQuery query, Observer observer)
1805
        throws DataException {
1806
        class LoadInBackGround implements Runnable {
1807

    
1808
            private final FeatureStore store;
1809
            private final FeatureQuery query;
1810
            private final Observer observer;
1811

    
1812
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1813
                Observer observer) {
1814
                this.store = store;
1815
                this.query = query;
1816
                this.observer = observer;
1817
            }
1818

    
1819
            void notify(FeatureStoreNotification theNotification) {
1820
                observer.update(store, theNotification);
1821
            }
1822

    
1823
            @Override
1824
            public void run() {
1825
                FeatureSet set = null;
1826
                try {
1827
                    set = store.getFeatureSet(query);
1828
                    notify(new DefaultFeatureStoreNotification(store,
1829
                        FeatureStoreNotification.LOAD_FINISHED, set));
1830
                } catch (Exception e) {
1831
                    notify(new DefaultFeatureStoreNotification(store,
1832
                        FeatureStoreNotification.LOAD_FINISHED, e));
1833
                } finally {
1834
                    dispose(set);
1835
                }
1836
            }
1837
        }
1838

    
1839
        checkNotInAppendMode();
1840
        if (query == null) {
1841
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1842
        }
1843
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1844
        Thread thread = new Thread(task, "Load Feature Set in background");
1845
        thread.start();
1846
    }
1847

    
1848
    @Override
1849
    public Feature getFeatureByReference(FeatureReference reference)
1850
        throws DataException {
1851
        checkNotInAppendMode();
1852
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1853
        FeatureType featureType;
1854
        if (ref.getFeatureTypeId() == null) {
1855
            featureType = this.getDefaultFeatureType();
1856
        } else {
1857
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1858
        }
1859
        return this.getFeatureByReference(reference, featureType);
1860
    }
1861

    
1862
    @Override
1863
    public Feature getFeatureByReference(FeatureReference reference,
1864
        FeatureType featureType) throws DataException {
1865
        checkNotInAppendMode();
1866
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1867
        if (this.mode == MODE_FULLEDIT) {
1868
            Feature f = featureManager.get(reference, this, featureType);
1869
            if (f != null) {
1870
                return f;
1871
            }
1872
        }
1873

    
1874
        FeatureType sourceFeatureType = featureType;
1875
        if (!this.transforms.isEmpty()) {
1876
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1877
        }
1878
        // TODO comprobar que el id es de este store
1879

    
1880
        DefaultFeature feature =
1881
            new DefaultFeature(this,
1882
                this.provider.getFeatureProviderByReference(
1883
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1884

    
1885
        if (!this.transforms.isEmpty()) {
1886
            return this.transforms.applyTransform(feature, featureType);
1887
        }
1888
        return feature;
1889
    }
1890

    
1891
    //
1892
    // ====================================================================
1893
    // Gestion de features
1894
    //
1895

    
1896
    private FeatureType fixFeatureType(DefaultFeatureType type)
1897
        throws DataException {
1898
        FeatureType original = this.getDefaultFeatureType();
1899

    
1900
        if ((type == null) || type.equals(original)) {
1901
            return original;
1902
        } else {
1903
            if (!type.isSubtypeOf(original)) {
1904
                Iterator iter = this.getFeatureTypes().iterator();
1905
                FeatureType tmpType;
1906
                boolean found = false;
1907
                while (iter.hasNext()) {
1908
                    tmpType = (FeatureType) iter.next();
1909
                    if (type.equals(tmpType)) {
1910
                        return type;
1911

    
1912
                    } else
1913
                        if (type.isSubtypeOf(tmpType)) {
1914
                            found = true;
1915
                            original = tmpType;
1916
                            break;
1917
                        }
1918

    
1919
                }
1920
                if (!found) {
1921
                    throw new IllegalFeatureTypeException(getName());
1922
                }
1923
            }
1924
        }
1925

    
1926
        // Checks that type has all fields of pk
1927
        // else add the missing attributes at the end.
1928
        if (!original.hasOID()) {
1929
            // Gets original pk attributes
1930
            DefaultEditableFeatureType edOriginal =
1931
                (DefaultEditableFeatureType) original.getEditable();
1932
            FeatureAttributeDescriptor orgAttr;
1933
            Iterator edOriginalIter = edOriginal.iterator();
1934
            while (edOriginalIter.hasNext()) {
1935
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1936
                if (!orgAttr.isPrimaryKey()) {
1937
                    edOriginalIter.remove();
1938
                }
1939
            }
1940

    
1941
            // Checks if all pk attributes are in type
1942
            Iterator typeIterator;
1943
            edOriginalIter = edOriginal.iterator();
1944
            FeatureAttributeDescriptor attr;
1945
            while (edOriginalIter.hasNext()) {
1946
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1947
                typeIterator = type.iterator();
1948
                while (typeIterator.hasNext()) {
1949
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1950
                    if (attr.getName().equals(orgAttr.getName())) {
1951
                        edOriginalIter.remove();
1952
                        break;
1953
                    }
1954
                }
1955
            }
1956

    
1957
            // add missing pk attributes if any
1958
            if (edOriginal.size() > 0) {
1959
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1960
                DefaultEditableFeatureType edType =
1961
                    (DefaultEditableFeatureType) original.getEditable();
1962
                edType.clear();
1963
                edType.addAll(type);
1964
                edType.addAll(edOriginal);
1965
                if (!isEditable) {
1966
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1967
                }
1968
            }
1969

    
1970
        }
1971

    
1972
        return type;
1973
    }
1974

    
1975
    @Override
1976
    public void validateFeatures(int mode) throws DataException {
1977
        FeatureSet collection = null;
1978
        DisposableIterator iter = null;
1979
        try {
1980
            checkNotInAppendMode();
1981
            collection = this.getFeatureSet();
1982
            iter = collection.fastIterator();
1983
            long previousVersionOfUpdate = currentVersionOfUpdate();
1984
            while (iter.hasNext()) {
1985
                ((DefaultFeature) iter.next()).validate(mode);
1986
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1987
                    throw new ConcurrentDataModificationException(getName());
1988
                }
1989
            }
1990
        } catch (Exception e) {
1991
            throw new ValidateFeaturesException(e, getName());
1992
        } finally {
1993
            dispose(iter);
1994
            dispose(collection);
1995
        }
1996
    }
1997

    
1998
    @Override
1999
    public FeatureType getDefaultFeatureType() throws DataException {
2000
        try {
2001

    
2002
            if (isEditing()) {
2003
                FeatureType auxFeatureType =
2004
                    featureTypeManager.getType(defaultFeatureType.getId());
2005
                if (auxFeatureType != null) {
2006
                    return avoidEditable(auxFeatureType);
2007
                }
2008
            }
2009
            FeatureType type = this.transforms.getDefaultFeatureType();
2010
            if (type != null) {
2011
                return avoidEditable(type);
2012
            }
2013

    
2014
            return avoidEditable(defaultFeatureType);
2015

    
2016
        } catch (Exception e) {
2017
            throw new GetFeatureTypeException(e, getName());
2018
        }
2019
    }
2020

    
2021
    private FeatureType avoidEditable(FeatureType ft) {
2022
        if (ft instanceof EditableFeatureType) {
2023
            return ((EditableFeatureType) ft).getNotEditableCopy();
2024
        } else {
2025
            return ft;
2026
        }
2027
    }
2028

    
2029
    @Override
2030
    public FeatureType getFeatureType(String featureTypeId)
2031
        throws DataException {
2032
        if (featureTypeId == null) {
2033
            return this.getDefaultFeatureType();
2034
        }
2035
        try {
2036
            if (isEditing()) {
2037
                FeatureType auxFeatureType =
2038
                    featureTypeManager.getType(featureTypeId);
2039
                if (auxFeatureType != null) {
2040
                    return auxFeatureType;
2041
                }
2042
            }
2043
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
2044
            if (type != null) {
2045
                return type;
2046
            }
2047
            Iterator iter = this.featureTypes.iterator();
2048
            while (iter.hasNext()) {
2049
                type = (FeatureType) iter.next();
2050
                if (type.getId().equals(featureTypeId)) {
2051
                    return type;
2052
                }
2053
            }
2054
            return null;
2055
        } catch (Exception e) {
2056
            throw new GetFeatureTypeException(e, getName());
2057
        }
2058
    }
2059

    
2060
    public FeatureType getProviderDefaultFeatureType() {
2061
        return defaultFeatureType;
2062
    }
2063

    
2064
    @Override
2065
    public List getFeatureTypes() throws DataException {
2066
        try {
2067
            List types;
2068
            if (isEditing()) {
2069
                types = new ArrayList();
2070
                Iterator it = featureTypes.iterator();
2071
                while (it.hasNext()) {
2072
                    FeatureType type = (FeatureType) it.next();
2073
                    FeatureType typeaux =
2074
                        featureTypeManager.getType(type.getId());
2075
                    if (typeaux != null) {
2076
                        types.add(typeaux);
2077
                    } else {
2078
                        types.add(type);
2079
                    }
2080
                }
2081
                it = featureTypeManager.newsIterator();
2082
                while (it.hasNext()) {
2083
                    FeatureType type = (FeatureType) it.next();
2084
                    types.add(type);
2085
                }
2086
            } else {
2087
                types = this.transforms.getFeatureTypes();
2088
                if (types == null) {
2089
                    types = featureTypes;
2090
                }
2091
            }
2092
            return Collections.unmodifiableList(types);
2093
        } catch (Exception e) {
2094
            throw new GetFeatureTypeException(e, getName());
2095
        }
2096
    }
2097

    
2098
    public List getProviderFeatureTypes() throws DataException {
2099
        return Collections.unmodifiableList(this.featureTypes);
2100
    }
2101

    
2102
    @Override
2103
    public Feature createFeature(FeatureProvider data) throws DataException {
2104
        DefaultFeature feature = new DefaultFeature(this, data);
2105
        return feature;
2106
    }
2107

    
2108
    public Feature createFeature(FeatureProvider data, FeatureType type)
2109
        throws DataException {
2110
        // FIXME: falta por implementar
2111
        // Comprobar si es un subtipo del feature de data
2112
        // y construir un feature usando el subtipo.
2113
        // Probablemente requiera generar una copia del data.
2114
        throw new NotYetImplemented();
2115
    }
2116

    
2117
    @Override
2118
    public EditableFeature createNewFeature(FeatureType type,
2119
        Feature defaultValues) throws DataException {
2120
        try {
2121
            FeatureProvider data = createNewFeatureProvider(type);
2122
            DefaultEditableFeature feature =
2123
                new DefaultEditableFeature(this, data);
2124
            feature.initializeValues(defaultValues);
2125
            data.setNew(true);
2126

    
2127
            return feature;
2128
        } catch (Exception e) {
2129
            throw new CreateFeatureException(e, getName());
2130
        }
2131
    }
2132

    
2133
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2134
        throws DataException {
2135
        type = this.fixFeatureType((DefaultFeatureType) type);
2136
        FeatureProvider data = this.provider.createFeatureProvider(type);
2137
        data.setNew(true);
2138
        if (type.hasOID() && (data.getOID() == null)) {
2139
            data.setOID(this.provider.createNewOID());
2140
        } else {
2141
            data.setOID(this.getTemporalOID());
2142
        }
2143
        return data;
2144

    
2145
    }
2146

    
2147
    @Override
2148
    public EditableFeature createNewFeature(FeatureType type,
2149
        boolean defaultValues) throws DataException {
2150
        try {
2151
            FeatureProvider data = createNewFeatureProvider(type);
2152
            DefaultEditableFeature feature =
2153
                new DefaultEditableFeature(this, data);
2154
            if (defaultValues) {
2155
                feature.initializeValues();
2156
            }
2157
            return feature;
2158
        } catch (Exception e) {
2159
            throw new CreateFeatureException(e, getName());
2160
        }
2161
    }
2162

    
2163
    @Override
2164
    public EditableFeature createNewFeature(boolean defaultValues)
2165
        throws DataException {
2166
        return this.createNewFeature(this.getDefaultFeatureType(),
2167
            defaultValues);
2168
    }
2169

    
2170
    @Override
2171
    public EditableFeature createNewFeature() throws DataException {
2172
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2173
    }
2174

    
2175
    @Override
2176
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2177
        FeatureType ft = this.getDefaultFeatureType();
2178
        EditableFeature f = this.createNewFeature(ft, false);
2179
                for( FeatureAttributeDescriptor desc : ft ) {
2180
                        try {
2181
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2182
                        } catch(Throwable th) {
2183
                                // Ignore
2184
                        }
2185
                }
2186
        return f;
2187
    }
2188

    
2189
    @Override
2190
    public EditableFeatureType createFeatureType() {
2191
        EditableFeatureType ftype = this.dataManager.createFeatureType();
2192
        return ftype;
2193
    }
2194

    
2195
    @Override
2196
    public EditableFeatureType createFeatureType(String id) {
2197
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
2198
        return ftype;
2199
    }
2200

    
2201
    //
2202
    // ====================================================================
2203
    // Index related methods
2204
    //
2205

    
2206
    @Override
2207
    public FeatureIndexes getIndexes() {
2208
        return this.indexes;
2209
    }
2210

    
2211
    @Override
2212
    public FeatureIndex createIndex(FeatureType featureType,
2213
        String attributeName, String indexName) throws DataException {
2214
        return createIndex(null, featureType, attributeName, indexName);
2215
    }
2216

    
2217
    @Override
2218
    public FeatureIndex createIndex(String indexTypeName,
2219
        FeatureType featureType, String attributeName, String indexName)
2220
        throws DataException {
2221

    
2222
        return createIndex(indexTypeName, featureType, attributeName,
2223
            indexName, false, null);
2224
    }
2225

    
2226
    @Override
2227
    public FeatureIndex createIndex(FeatureType featureType,
2228
        String attributeName, String indexName, Observer observer)
2229
        throws DataException {
2230
        return createIndex(null, featureType, attributeName, indexName,
2231
            observer);
2232
    }
2233

    
2234
    @Override
2235
    public FeatureIndex createIndex(String indexTypeName,
2236
        FeatureType featureType, String attributeName, String indexName,
2237
        final Observer observer) throws DataException {
2238

    
2239
        return createIndex(indexTypeName, featureType, attributeName,
2240
            indexName, true, observer);
2241
    }
2242

    
2243
    private FeatureIndex createIndex(String indexTypeName,
2244
        FeatureType featureType, String attributeName, String indexName,
2245
        boolean background, final Observer observer) throws DataException {
2246

    
2247
        checkNotInAppendMode();
2248
        FeatureIndexProviderServices index;
2249
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2250
                featureType, indexName,
2251
                featureType.getAttributeDescriptor(attributeName));
2252

    
2253
        try {
2254
            index.fill(background, observer);
2255
        } catch (FeatureIndexException e) {
2256
            throw new InitializeException(index.getName(), e);
2257
        }
2258

    
2259
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2260
        return index;
2261
    }
2262

    
2263
    //
2264
    // ====================================================================
2265
    // Transforms related methods
2266
    //
2267

    
2268
    @Override
2269
    public FeatureStoreTransforms getTransforms() {
2270
        return this.transforms;
2271
    }
2272

    
2273
    @Override
2274
    public FeatureQuery createFeatureQuery() {
2275
        return new DefaultFeatureQuery();
2276
    }
2277

    
2278
    @Override
2279
    public DataQuery createQuery() {
2280
        return createFeatureQuery();
2281
    }
2282

    
2283
    //
2284
    // ====================================================================
2285
    // UndoRedo related methods
2286
    //
2287

    
2288
    @Override
2289
    public boolean canRedo() {
2290
        return commands.canRedo();
2291
    }
2292

    
2293
    @Override
2294
    public boolean canUndo() {
2295
        return commands.canUndo();
2296
    }
2297

    
2298
    @Override
2299
    public void redo(int num) throws RedoException {
2300
        for (int i = 0; i < num; i++) {
2301
            redo();
2302
        }
2303
    }
2304

    
2305
    @Override
2306
    public void undo(int num) throws UndoException {
2307
        for (int i = 0; i < num; i++) {
2308
            undo();
2309
        }
2310
    }
2311

    
2312
    //
2313
    // ====================================================================
2314
    // Metadata related methods
2315
    //
2316

    
2317
    @Override
2318
    public Object getMetadataID() {
2319
        return this.provider.getSourceId();
2320
    }
2321

    
2322
    @Override
2323
    public void delegate(DynObject dynObject) {
2324
        this.metadata.delegate(dynObject);
2325
    }
2326

    
2327
    @Override
2328
    public DynClass getDynClass() {
2329
        return this.metadata.getDynClass();
2330
    }
2331

    
2332
    @Override
2333
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2334
                if( this.transforms.hasDynValue(name) ) {
2335
                        return this.transforms.getDynValue(name);
2336
                }
2337
                if (this.metadata.hasDynValue(name)) {
2338
                        return this.metadata.getDynValue(name);
2339
                }
2340
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2341
                        return this.provider.getProviderName();
2342
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2343
                        return this.provider.getSourceId();
2344
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2345
                        try {
2346
                                return this.getDefaultFeatureType();
2347
                        } catch (DataException e) {
2348
                                return null;
2349
                        }
2350
                }
2351
                return this.metadata.getDynValue(name);
2352
        }
2353

    
2354
    @Override
2355
    public boolean hasDynValue(String name) {
2356
                if( this.transforms.hasDynValue(name) ) {
2357
                        return true;
2358
                }
2359
        return this.metadata.hasDynValue(name);
2360
    }
2361

    
2362
    @Override
2363
    public boolean hasDynMethod(String name) {
2364
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2365
    }
2366

    
2367
    @Override
2368
    public void implement(DynClass dynClass) {
2369
        this.metadata.implement(dynClass);
2370
    }
2371

    
2372
    @Override
2373
    public Object invokeDynMethod(String name, Object[] args)
2374
        throws DynMethodException {
2375
        return this.metadata.invokeDynMethod(this, name, args);
2376
    }
2377

    
2378
    @Override
2379
    public Object invokeDynMethod(int code, Object[] args)
2380
        throws DynMethodException {
2381
        return this.metadata.invokeDynMethod(this, code, args);
2382
    }
2383

    
2384
    @Override
2385
    public void setDynValue(String name, Object value)
2386
        throws DynFieldNotFoundException {
2387
                if( this.transforms.hasDynValue(name) ) {
2388
                        this.transforms.setDynValue(name, value);
2389
                        return;
2390
                }
2391
        this.metadata.setDynValue(name, value);
2392

    
2393
    }
2394

    
2395
    /*
2396
     * (non-Javadoc)
2397
     *
2398
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2399
     */
2400
    @Override
2401
    public Set getMetadataChildren() {
2402
        return this.metadataChildren;
2403
    }
2404

    
2405
    /*
2406
     * (non-Javadoc)
2407
     *
2408
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2409
     */
2410
    @Override
2411
    public String getMetadataName() {
2412
        return this.provider.getProviderName();
2413
    }
2414

    
2415
    public FeatureTypeManager getFeatureTypeManager() {
2416
        return this.featureTypeManager;
2417
    }
2418

    
2419
    @Override
2420
    public long getFeatureCount() throws DataException {
2421
        if (featureCount == null) {
2422
            featureCount = this.provider.getFeatureCount();
2423
        }
2424
        if (this.isEditing()) {
2425
            if(this.isAppending()) {
2426
                try{
2427
                    throw new IllegalStateException();
2428
                } catch(IllegalStateException e) {
2429
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND");
2430
                    e.printStackTrace();
2431
                }
2432
                return -1;
2433
            } else {
2434
                return featureCount
2435
                    + this.featureManager.getDeltaSize();
2436
            }
2437
        }
2438
        return featureCount;
2439
    }
2440

    
2441
    private Long getTemporalOID() {
2442
        return this.temporalOid++;
2443
    }
2444

    
2445
    @Override
2446
    public FeatureType getProviderFeatureType(String featureTypeId) {
2447
        if (featureTypeId == null) {
2448
            return this.defaultFeatureType;
2449
        }
2450
        FeatureType type;
2451
        Iterator iter = this.featureTypes.iterator();
2452
        while (iter.hasNext()) {
2453
            type = (FeatureType) iter.next();
2454
            if (type.getId().equals(featureTypeId)) {
2455
                return type;
2456
            }
2457
        }
2458
        return null;
2459
    }
2460

    
2461
    @Override
2462
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2463
        return ((DefaultFeature) feature).getData();
2464
    }
2465

    
2466
    @Override
2467
    public DataStore getStore() {
2468
        return this;
2469
    }
2470

    
2471
    @Override
2472
    public FeatureStore getFeatureStore() {
2473
        return this;
2474
    }
2475

    
2476
    @Override
2477
    public void createCache(String name, DynObject parameters)
2478
        throws DataException {
2479
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2480
        if (cache == null) {
2481
            throw new CreateException("FeaureCacheProvider", null);
2482
        }
2483
        cache.apply(this, provider);
2484
        provider = cache;
2485

    
2486
        featureCount = null;
2487
    }
2488

    
2489
    @Override
2490
    public FeatureCache getCache() {
2491
        return cache;
2492
    }
2493

    
2494
    @Override
2495
    public void clear() {
2496
        if (metadata != null) {
2497
            metadata.clear();
2498
        }
2499
    }
2500

    
2501
    @Override
2502
    public String getName() {
2503
        if( this.provider != null ) {
2504
            return this.provider.getName();
2505
        }
2506
        if( this.parameters instanceof HasAFile ) {
2507
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2508
        }
2509
        return "unknow";
2510
    }
2511

    
2512
    @Override
2513
    public String getFullName() {
2514
        try {
2515
            if( this.provider!=null ) {
2516
                return this.provider.getFullName();
2517
            }
2518
            if( this.parameters instanceof HasAFile ) {
2519
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2520
            }
2521
            return null;
2522
        } catch(Throwable th) {
2523
            return null;
2524
        }
2525
    }
2526

    
2527
    @Override
2528
    public String getProviderName() {
2529
        if( this.provider!=null ) {
2530
            return this.provider.getProviderName();
2531
        }
2532
        if( this.parameters != null ) {
2533
            return this.parameters.getDataStoreName();
2534
        }
2535
        return null;
2536

    
2537
    }
2538

    
2539
    @Override
2540
    public boolean isKnownEnvelope() {
2541
        return this.provider.isKnownEnvelope();
2542
    }
2543

    
2544
    @Override
2545
    public boolean hasRetrievedFeaturesLimit() {
2546
        return this.provider.hasRetrievedFeaturesLimit();
2547
    }
2548

    
2549
    @Override
2550
    public int getRetrievedFeaturesLimit() {
2551
        return this.provider.getRetrievedFeaturesLimit();
2552
    }
2553

    
2554
    @Override
2555
    public Interval getInterval() {
2556
        if( this.timeSupport!=null ) {
2557
            return this.timeSupport.getInterval();
2558
        }
2559
        return this.provider.getInterval();
2560
    }
2561

    
2562
    @Override
2563
    public Collection getTimes() {
2564
        if( this.timeSupport!=null ) {
2565
            return this.timeSupport.getTimes();
2566
        }
2567
        return this.provider.getTimes();
2568
    }
2569

    
2570
    @Override
2571
    public Collection getTimes(Interval interval) {
2572
        if( this.timeSupport!=null ) {
2573
            return this.timeSupport.getTimes(interval);
2574
        }
2575
        return this.provider.getTimes(interval);
2576
    }
2577

    
2578
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2579
        if( this.isEditing() ) {
2580
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' while store is editing.");
2581
        }
2582
        if( !this.transforms.isEmpty() ) {
2583
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"' if has transforms.");
2584
        }
2585
        FeatureType ft = this.defaultFeatureType;
2586
        FeatureAttributeDescriptor attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2587
        if( attr == null ) {
2588
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2589
        }
2590
        EditableFeatureType eft = ft.getEditable();
2591
        attr = eft.getAttributeDescriptor(timeSupport.getAttributeName());
2592
        if( attr != null ) {
2593
            if( !(attr.getFeatureAttributeEmulator() instanceof FeatureStoreTimeSupport) ) {
2594
                throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2595
            }
2596
            eft.remove(attr.getName());
2597
        }
2598
        EditableFeatureAttributeDescriptor attrTime = eft.add(
2599
            timeSupport.getAttributeName(), 
2600
            timeSupport.getDataType()
2601
        );
2602
        attrTime.setIsTime(true);
2603
        attrTime.setFeatureAttributeEmulator(timeSupport);
2604
        eft.setDefaultTimeAttributeName(timeSupport.getAttributeName());
2605
        this.defaultFeatureType = eft.getNotEditableCopy();
2606
        
2607
        this.timeSupport = timeSupport;
2608
    }
2609

    
2610
    @Override
2611
    public Object clone() throws CloneNotSupportedException {
2612

    
2613
        DataStoreParameters dsp = getParameters();
2614

    
2615
        DefaultFeatureStore cloned_store = null;
2616

    
2617
        try {
2618
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2619
                openStore(this.getProviderName(), dsp);
2620
            if (transforms != null) {
2621
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2622
                cloned_store.transforms.setStoreForClone(cloned_store);
2623
            }
2624
        } catch (Exception e) {
2625
            throw new CloneException(e);
2626
        }
2627
        return cloned_store;
2628

    
2629
    }
2630

    
2631
    @Override
2632
    public Feature getFeature(DynObject dynobject) {
2633
        if (dynobject instanceof DynObjectFeatureFacade){
2634
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2635
            return f;
2636
        }
2637
        return null;
2638
    }
2639

    
2640
    @Override
2641
    public Iterator iterator() {
2642
        try {
2643
            return this.getFeatureSet().fastIterator();
2644
        } catch (DataException ex) {
2645
            throw new RuntimeException(ex);
2646
        }
2647
    }
2648

    
2649
    @Override
2650
    public ExpressionBuilder createExpressionBuilder() {
2651
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2652
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2653
        }
2654
        return new SQLBuilderBase();
2655
    }
2656

    
2657
    @Override
2658
    public ExpressionBuilder createExpression() {
2659
        return createExpressionBuilder();
2660
    }
2661

    
2662
    public FeatureSet features() throws DataException {
2663
        // This is to avoid jython to create a property with this name
2664
        // to access method getFeatures.
2665
        return this.getFeatureSet();
2666
    }
2667

    
2668
    @Override
2669
    public DataStoreProviderFactory getProviderFactory() {
2670
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2671
        return factory;
2672
    }
2673

    
2674
    @Override
2675
    public void useCache(String providerName, DynObject parameters) throws DataException {
2676
        throw new UnsupportedOperationException();
2677
    }
2678

    
2679
    @Override
2680
    public boolean isBroken() {
2681
        return this.state.isBroken();
2682
    }
2683

    
2684
    @Override
2685
    public Throwable getBreakingsCause() {
2686
            return this.state.getBreakingsCause();
2687
    }
2688

    
2689
    @Override
2690
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2691
//      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2692
//      if( !factory.supportNumericOID() ) {
2693
//          return null;
2694
//      }
2695
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2696
      return wrappedIndex;
2697
  }
2698
}