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

History | View | Annotate | Download (85.9 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.cresques.cts.IProjection;
42

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

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

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

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

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

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

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

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

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

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

    
193
    private DefaultDataManager dataManager = null;
194

    
195
    private FeatureStoreProvider provider = null;
196

    
197
    private DefaultFeatureIndexes indexes;
198

    
199
    private DefaultFeatureStoreTransforms transforms;
200

    
201
    DelegatedDynObject metadata;
202

    
203
    private Set metadataChildren;
204

    
205
    private Long featureCount = null;
206

    
207
    private long temporalOid = 0;
208

    
209
    private FeatureCacheProvider cache;
210

    
211
    StateInformation state;
212

    
213
    FeatureStoreTimeSupport timeSupport;
214

    
215

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

    
218
        private static final long serialVersionUID = 4109026189635185666L;
219

    
220
        private boolean broken;
221
        private Throwable breakingsCause;
222

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

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

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

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

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

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

    
254

    
255

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

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

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

    
273
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
274

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

    
280
        this.dataManager = (DefaultDataManager) dataManager;
281

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

    
290
    }
291

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
533
        }
534

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

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

    
542
    }
543

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

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

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

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

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

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

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

    
655
                    }
656

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

    
662

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
856
    }
857

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

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

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

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

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

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

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

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

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

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

    
921
    }
922

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

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

    
932
    }
933

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

    
938
    }
939

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

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

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

    
958
    }
959

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

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

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

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

    
990
    //
991
    // ====================================================================
992
    // Edicion
993
    //
994

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

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

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

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

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

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

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

    
1035
        }
1036

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

    
1041
        featureCount = null;
1042

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1226
    private static EditableFeature lastChangedFeature = null;
1227

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

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

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

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

    
1266
        waitForIndexes();
1267

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

    
1280

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

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

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

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

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

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

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

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

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

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

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

    
1379
    @Override
1380
    synchronized public void cancelEditing() throws DataException {
1381
        spatialManager.cancelModifies();
1382
        try {
1383
            checkInEditingMode();
1384

    
1385
            boolean clearSelection = this.hasStrongChanges;
1386
            if (this.selection instanceof FeatureReferenceSelection) {
1387
                clearSelection = this.hasInserts;
1388
            }
1389
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1390
            exitEditingMode();
1391
            if (clearSelection) {
1392
                ((FeatureSelection) this.getSelection()).deselectAll();
1393
            }
1394
            updateIndexes();
1395
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1396
        } catch (Exception e) {
1397
            throw new StoreCancelEditingException(e, this.getName());
1398
        }
1399
    }
1400

    
1401
    @Override
1402
    synchronized public void finishEditing() throws DataException {
1403
        LOG.debug("finish editing of mode: {}", mode);
1404
        try {
1405

    
1406
            /*
1407
             * Selection needs to be cleared when editing stops
1408
             * to prevent conflicts with selection remaining from
1409
             * editing mode.
1410
             */
1411
//            ((FeatureSelection) this.getSelection()).deselectAll();
1412

    
1413
            switch (mode) {
1414
            case MODE_QUERY:
1415
                throw new NeedEditingModeException(this.getName());
1416

    
1417
            case MODE_APPEND:
1418
                if( selection!=null ) {
1419
                    selection = null;
1420
                }
1421
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1422
                provider.endAppend();
1423
                exitEditingMode();
1424
                updateIndexes();
1425
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1426
                break;
1427

    
1428
            case MODE_FULLEDIT:
1429
                if (hasStrongChanges && !this.allowWrite()) {
1430
                    throw new WriteNotAllowedException(getName());
1431
                }
1432
                if(featureManager.isSelectionCompromised() && selection!=null ) {
1433
                    selection = null;
1434
                }
1435
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1436
                if (hasStrongChanges) {
1437
                    validateFeatures(Feature.FINISH_EDITING);
1438

    
1439
                    /*
1440
                     * This will throw a PerformEditingExceptionif the provider
1441
                     * does not accept the changes (for example, an invalid field name)
1442
                     */
1443
                    provider.performChanges(featureManager.getDeleted(),
1444
                        featureManager.getInserted(),
1445
                        featureManager.getUpdated(),
1446
                        featureTypeManager.getFeatureTypesChanged());
1447
                }
1448
                exitEditingMode();
1449
                updateIndexes();
1450
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1451
                break;
1452
            }
1453
        } catch (PerformEditingException pee) {
1454
            throw new WriteException(provider.getSourceId().toString(), pee);
1455
        } catch (Exception e) {
1456
            throw new FinishEditingException(e);
1457
        }
1458
    }
1459

    
1460
    /**
1461
     * Save changes in the provider without leaving the edit mode.
1462
     * Do not call observers to communicate a change of ediding mode.
1463
     * The operation's history is eliminated to prevent inconsistencies
1464
     * in the data.
1465
     *
1466
     * @throws DataException
1467
     */
1468
    @Override
1469
    synchronized public void commitChanges() throws DataException {
1470
      LOG.debug("commitChanges of mode: {}", mode);
1471
      if( !canCommitChanges() ) {
1472
              throw new WriteNotAllowedException(getName());
1473
      }
1474
      try {
1475
        switch (mode) {
1476
        case MODE_QUERY:
1477
          throw new NeedEditingModeException(this.getName());
1478

    
1479
        case MODE_APPEND:
1480
          this.provider.endAppend();
1481
          exitEditingMode();
1482
          invalidateIndexes();
1483
          this.provider.beginAppend();
1484
          hasInserts = false;
1485
          break;
1486

    
1487
        case MODE_FULLEDIT:
1488
          if (hasStrongChanges && !this.allowWrite()) {
1489
            throw new WriteNotAllowedException(getName());
1490
          }
1491
          if (hasStrongChanges) {
1492
            validateFeatures(Feature.FINISH_EDITING);
1493
            provider.performChanges(featureManager.getDeleted(),
1494
              featureManager.getInserted(),
1495
              featureManager.getUpdated(),
1496
              featureTypeManager.getFeatureTypesChanged());
1497
          }
1498
          invalidateIndexes();
1499
          featureManager =
1500
            new FeatureManager(new MemoryExpansionAdapter());
1501
          featureTypeManager =
1502
            new FeatureTypeManager(this, new MemoryExpansionAdapter());
1503
          spatialManager =
1504
            new SpatialManager(this, provider.getEnvelope());
1505

    
1506
          commands =
1507
            new DefaultFeatureCommandsStack(this, featureManager,
1508
              spatialManager, featureTypeManager);
1509
          featureCount = null;
1510
          hasStrongChanges = false;
1511
          hasInserts = false;
1512
          break;
1513
        }
1514
      } catch (Exception e) {
1515
        throw new FinishEditingException(e);
1516
      }
1517
    }
1518

    
1519
    @Override
1520
    synchronized public boolean canCommitChanges() throws DataException {
1521
        if ( !this.allowWrite()) {
1522
                return false;
1523
        }
1524
            switch (mode) {
1525
            default:
1526
        case MODE_QUERY:
1527
                return false;
1528

    
1529
        case MODE_APPEND:
1530
                return true;
1531

    
1532
        case MODE_FULLEDIT:
1533
            List types = this.getFeatureTypes();
1534
            for( int i=0; i<types.size(); i++ ) {
1535
                    Object type = types.get(i);
1536
                    if( type instanceof DefaultEditableFeatureType ) {
1537
                            if( ((DefaultEditableFeatureType)type).hasStrongChanges() ) {
1538
                                    return false;
1539
                            }
1540
                    }
1541
            }
1542
            return true;
1543
            }
1544
    }
1545

    
1546
    @Override
1547
    public void beginEditingGroup(String description)
1548
        throws NeedEditingModeException {
1549
        checkInEditingMode();
1550
        commands.startComplex(description);
1551
    }
1552

    
1553
    @Override
1554
    public void endEditingGroup() throws NeedEditingModeException {
1555
        checkInEditingMode();
1556
        commands.endComplex();
1557
    }
1558

    
1559
    @Override
1560
    public boolean isAppendModeSupported() {
1561
        return this.provider.supportsAppendMode();
1562
    }
1563

    
1564
    @Override
1565
    public void export(DataServerExplorer explorer, String provider,
1566
        NewFeatureStoreParameters params) throws DataException {
1567

    
1568
        if (this.getFeatureTypes().size() != 1) {
1569
            throw new NotYetImplemented(
1570
                "export whith more than one type not yet implemented");
1571
        }
1572
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1573
        FeatureStore target = null;
1574
        FeatureSet features = null;
1575
        DisposableIterator iterator = null;
1576
        try {
1577
            FeatureType type = this.getDefaultFeatureType();
1578
            if ((params.getDefaultFeatureType() == null)
1579
                || (params.getDefaultFeatureType().size() == 0)) {
1580
                params.setDefaultFeatureType(type.getEditable());
1581

    
1582
            }
1583
            explorer.add(provider, params, true);
1584

    
1585
            DataManager manager = DALLocator.getDataManager();
1586
            target = (FeatureStore) manager.openStore(provider, params);
1587
            FeatureType targetType = target.getDefaultFeatureType();
1588

    
1589
            target.edit(MODE_APPEND);
1590
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1591
            if (featureSelection.getSize() > 0) {
1592
                features = this.getFeatureSelection();
1593
            } else {
1594
                if ((pk != null) && (pk.length > 0)) {
1595
                    FeatureQuery query = createFeatureQuery();
1596
                    for (int i = 0; i < pk.length; i++) {
1597
                        query.getOrder().add(pk[i].getName(), true);
1598
                    }
1599
                    features = this.getFeatureSet(query);
1600
                } else {
1601
                    features = this.getFeatureSet();
1602
                }
1603
            }
1604
            iterator = features.fastIterator();
1605
            while (iterator.hasNext()) {
1606
                DefaultFeature feature = (DefaultFeature) iterator.next();
1607
                target.insert(target.createNewFeature(targetType, feature));
1608
            }
1609
            target.finishEditing();
1610
            target.dispose();
1611
        } catch (Exception e) {
1612
            throw new DataExportException(e, params.toString());
1613
        } finally {
1614
            dispose(iterator);
1615
            dispose(features);
1616
            dispose(target);
1617
        }
1618
    }
1619

    
1620
    //
1621
    // ====================================================================
1622
    // Obtencion de datos
1623
    // getDataCollection, getFeatureCollection
1624
    //
1625

    
1626
    @Override
1627
    public DataSet getDataSet() throws DataException {
1628
        checkNotInAppendMode();
1629
        FeatureQuery query =
1630
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1631
        return new DefaultFeatureSet(this, query);
1632
    }
1633

    
1634
    @Override
1635
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1636
        checkNotInAppendMode();
1637
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1638
    }
1639

    
1640
    @Override
1641
    public void getDataSet(Observer observer) throws DataException {
1642
        checkNotInAppendMode();
1643
        this.getFeatureSet(null, observer);
1644
    }
1645

    
1646
    @Override
1647
    public void getDataSet(DataQuery dataQuery, Observer observer)
1648
        throws DataException {
1649
        checkNotInAppendMode();
1650
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1651
    }
1652

    
1653
    @Override
1654
    public FeatureSet getFeatureSet() throws DataException {
1655
        return this.getFeatureSet((FeatureQuery)null);
1656
    }
1657

    
1658
    @Override
1659
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1660
        throws DataException {
1661
        checkNotInAppendMode();
1662
        if( featureQuery==null ) {
1663
            featureQuery = new DefaultFeatureQuery(this.getDefaultFeatureType());
1664
        }
1665
        return new DefaultFeatureSet(this, featureQuery);
1666
    }
1667

    
1668
    @Override
1669
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1670
        try {
1671
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1672
            return pager.asList();
1673
        } catch (BaseException ex) {
1674
            throw new RuntimeException("Can't create the list of features.", ex);
1675
        }
1676
    }
1677

    
1678
    @Override
1679
    public List<Feature> getFeatures() {
1680
        return this.getFeatures(null, 500);
1681
    }
1682

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

    
1693
    @Override
1694
    public void accept(Visitor visitor, DataQuery dataQuery)
1695
        throws BaseException {
1696
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1697
        try {
1698
            set.accept(visitor);
1699
        } finally {
1700
            set.dispose();
1701
        }
1702
    }
1703

    
1704
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1705
        throws DataException {
1706
        DefaultFeatureType fType =
1707
            (DefaultFeatureType) this.getFeatureType(featureQuery
1708
                .getFeatureTypeId());
1709
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1710
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1711
        }
1712
        return fType;
1713
    }
1714

    
1715
    @Override
1716
    public void getFeatureSet(Observer observer) throws DataException {
1717
        checkNotInAppendMode();
1718
        this.getFeatureSet(null, observer);
1719
    }
1720

    
1721
    @Override
1722
    public void getFeatureSet(FeatureQuery query, Observer observer)
1723
        throws DataException {
1724
        class LoadInBackGround implements Runnable {
1725

    
1726
            private final FeatureStore store;
1727
            private final FeatureQuery query;
1728
            private final Observer observer;
1729

    
1730
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1731
                Observer observer) {
1732
                this.store = store;
1733
                this.query = query;
1734
                this.observer = observer;
1735
            }
1736

    
1737
            void notify(FeatureStoreNotification theNotification) {
1738
                observer.update(store, theNotification);
1739
            }
1740

    
1741
            @Override
1742
            public void run() {
1743
                FeatureSet set = null;
1744
                try {
1745
                    set = store.getFeatureSet(query);
1746
                    notify(new DefaultFeatureStoreNotification(store,
1747
                        FeatureStoreNotification.LOAD_FINISHED, set));
1748
                } catch (Exception e) {
1749
                    notify(new DefaultFeatureStoreNotification(store,
1750
                        FeatureStoreNotification.LOAD_FINISHED, e));
1751
                } finally {
1752
                    dispose(set);
1753
                }
1754
            }
1755
        }
1756

    
1757
        checkNotInAppendMode();
1758
        if (query == null) {
1759
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1760
        }
1761
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1762
        Thread thread = new Thread(task, "Load Feature Set in background");
1763
        thread.start();
1764
    }
1765

    
1766
    @Override
1767
    public Feature getFeatureByReference(FeatureReference reference)
1768
        throws DataException {
1769
        checkNotInAppendMode();
1770
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1771
        FeatureType featureType;
1772
        if (ref.getFeatureTypeId() == null) {
1773
            featureType = this.getDefaultFeatureType();
1774
        } else {
1775
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1776
        }
1777
        return this.getFeatureByReference(reference, featureType);
1778
    }
1779

    
1780
    @Override
1781
    public Feature getFeatureByReference(FeatureReference reference,
1782
        FeatureType featureType) throws DataException {
1783
        checkNotInAppendMode();
1784
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1785
        if (this.mode == MODE_FULLEDIT) {
1786
            Feature f = featureManager.get(reference, this, featureType);
1787
            if (f != null) {
1788
                return f;
1789
            }
1790
        }
1791

    
1792
        FeatureType sourceFeatureType = featureType;
1793
        if (!this.transforms.isEmpty()) {
1794
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1795
        }
1796
        // TODO comprobar que el id es de este store
1797

    
1798
        DefaultFeature feature =
1799
            new DefaultFeature(this,
1800
                this.provider.getFeatureProviderByReference(
1801
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1802

    
1803
        if (!this.transforms.isEmpty()) {
1804
            return this.transforms.applyTransform(feature, featureType);
1805
        }
1806
        return feature;
1807
    }
1808

    
1809
    //
1810
    // ====================================================================
1811
    // Gestion de features
1812
    //
1813

    
1814
    private FeatureType fixFeatureType(DefaultFeatureType type)
1815
        throws DataException {
1816
        FeatureType original = this.getDefaultFeatureType();
1817

    
1818
        if ((type == null) || type.equals(original)) {
1819
            return original;
1820
        } else {
1821
            if (!type.isSubtypeOf(original)) {
1822
                Iterator iter = this.getFeatureTypes().iterator();
1823
                FeatureType tmpType;
1824
                boolean found = false;
1825
                while (iter.hasNext()) {
1826
                    tmpType = (FeatureType) iter.next();
1827
                    if (type.equals(tmpType)) {
1828
                        return type;
1829

    
1830
                    } else
1831
                        if (type.isSubtypeOf(tmpType)) {
1832
                            found = true;
1833
                            original = tmpType;
1834
                            break;
1835
                        }
1836

    
1837
                }
1838
                if (!found) {
1839
                    throw new IllegalFeatureTypeException(getName());
1840
                }
1841
            }
1842
        }
1843

    
1844
        // Checks that type has all fields of pk
1845
        // else add the missing attributes at the end.
1846
        if (!original.hasOID()) {
1847
            // Gets original pk attributes
1848
            DefaultEditableFeatureType edOriginal =
1849
                (DefaultEditableFeatureType) original.getEditable();
1850
            FeatureAttributeDescriptor orgAttr;
1851
            Iterator edOriginalIter = edOriginal.iterator();
1852
            while (edOriginalIter.hasNext()) {
1853
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1854
                if (!orgAttr.isPrimaryKey()) {
1855
                    edOriginalIter.remove();
1856
                }
1857
            }
1858

    
1859
            // Checks if all pk attributes are in type
1860
            Iterator typeIterator;
1861
            edOriginalIter = edOriginal.iterator();
1862
            FeatureAttributeDescriptor attr;
1863
            while (edOriginalIter.hasNext()) {
1864
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1865
                typeIterator = type.iterator();
1866
                while (typeIterator.hasNext()) {
1867
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1868
                    if (attr.getName().equals(orgAttr.getName())) {
1869
                        edOriginalIter.remove();
1870
                        break;
1871
                    }
1872
                }
1873
            }
1874

    
1875
            // add missing pk attributes if any
1876
            if (edOriginal.size() > 0) {
1877
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1878
                DefaultEditableFeatureType edType =
1879
                    (DefaultEditableFeatureType) original.getEditable();
1880
                edType.clear();
1881
                edType.addAll(type);
1882
                edType.addAll(edOriginal);
1883
                if (!isEditable) {
1884
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1885
                }
1886
            }
1887

    
1888
        }
1889

    
1890
        return type;
1891
    }
1892

    
1893
    @Override
1894
    public void validateFeatures(int mode) throws DataException {
1895
        FeatureSet collection = null;
1896
        DisposableIterator iter = null;
1897
        try {
1898
            checkNotInAppendMode();
1899
            collection = this.getFeatureSet();
1900
            iter = collection.fastIterator();
1901
            long previousVersionOfUpdate = currentVersionOfUpdate();
1902
            while (iter.hasNext()) {
1903
                ((DefaultFeature) iter.next()).validate(mode);
1904
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1905
                    throw new ConcurrentDataModificationException(getName());
1906
                }
1907
            }
1908
        } catch (Exception e) {
1909
            throw new ValidateFeaturesException(e, getName());
1910
        } finally {
1911
            dispose(iter);
1912
            dispose(collection);
1913
        }
1914
    }
1915

    
1916
    @Override
1917
    public FeatureType getDefaultFeatureType() throws DataException {
1918
        try {
1919

    
1920
            if (isEditing()) {
1921
                FeatureType auxFeatureType =
1922
                    featureTypeManager.getType(defaultFeatureType.getId());
1923
                if (auxFeatureType != null) {
1924
                    return avoidEditable(auxFeatureType);
1925
                }
1926
            }
1927
            FeatureType type = this.transforms.getDefaultFeatureType();
1928
            if (type != null) {
1929
                return avoidEditable(type);
1930
            }
1931

    
1932
            return avoidEditable(defaultFeatureType);
1933

    
1934
        } catch (Exception e) {
1935
            throw new GetFeatureTypeException(e, getName());
1936
        }
1937
    }
1938

    
1939
    private FeatureType avoidEditable(FeatureType ft) {
1940
        if (ft instanceof EditableFeatureType) {
1941
            return ((EditableFeatureType) ft).getNotEditableCopy();
1942
        } else {
1943
            return ft;
1944
        }
1945
    }
1946

    
1947
    @Override
1948
    public FeatureType getFeatureType(String featureTypeId)
1949
        throws DataException {
1950
        if (featureTypeId == null) {
1951
            return this.getDefaultFeatureType();
1952
        }
1953
        try {
1954
            if (isEditing()) {
1955
                FeatureType auxFeatureType =
1956
                    featureTypeManager.getType(featureTypeId);
1957
                if (auxFeatureType != null) {
1958
                    return auxFeatureType;
1959
                }
1960
            }
1961
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1962
            if (type != null) {
1963
                return type;
1964
            }
1965
            Iterator iter = this.featureTypes.iterator();
1966
            while (iter.hasNext()) {
1967
                type = (FeatureType) iter.next();
1968
                if (type.getId().equals(featureTypeId)) {
1969
                    return type;
1970
                }
1971
            }
1972
            return null;
1973
        } catch (Exception e) {
1974
            throw new GetFeatureTypeException(e, getName());
1975
        }
1976
    }
1977

    
1978
    public FeatureType getProviderDefaultFeatureType() {
1979
        return defaultFeatureType;
1980
    }
1981

    
1982
    @Override
1983
    public List getFeatureTypes() throws DataException {
1984
        try {
1985
            List types;
1986
            if (isEditing()) {
1987
                types = new ArrayList();
1988
                Iterator it = featureTypes.iterator();
1989
                while (it.hasNext()) {
1990
                    FeatureType type = (FeatureType) it.next();
1991
                    FeatureType typeaux =
1992
                        featureTypeManager.getType(type.getId());
1993
                    if (typeaux != null) {
1994
                        types.add(typeaux);
1995
                    } else {
1996
                        types.add(type);
1997
                    }
1998
                }
1999
                it = featureTypeManager.newsIterator();
2000
                while (it.hasNext()) {
2001
                    FeatureType type = (FeatureType) it.next();
2002
                    types.add(type);
2003
                }
2004
            } else {
2005
                types = this.transforms.getFeatureTypes();
2006
                if (types == null) {
2007
                    types = featureTypes;
2008
                }
2009
            }
2010
            return Collections.unmodifiableList(types);
2011
        } catch (Exception e) {
2012
            throw new GetFeatureTypeException(e, getName());
2013
        }
2014
    }
2015

    
2016
    public List getProviderFeatureTypes() throws DataException {
2017
        return Collections.unmodifiableList(this.featureTypes);
2018
    }
2019

    
2020
    @Override
2021
    public Feature createFeature(FeatureProvider data) throws DataException {
2022
        DefaultFeature feature = new DefaultFeature(this, data);
2023
        return feature;
2024
    }
2025

    
2026
    public Feature createFeature(FeatureProvider data, FeatureType type)
2027
        throws DataException {
2028
        // FIXME: falta por implementar
2029
        // Comprobar si es un subtipo del feature de data
2030
        // y construir un feature usando el subtipo.
2031
        // Probablemente requiera generar una copia del data.
2032
        throw new NotYetImplemented();
2033
    }
2034

    
2035
    @Override
2036
    public EditableFeature createNewFeature(FeatureType type,
2037
        Feature defaultValues) throws DataException {
2038
        try {
2039
            FeatureProvider data = createNewFeatureProvider(type);
2040
            DefaultEditableFeature feature =
2041
                new DefaultEditableFeature(this, data);
2042
            feature.initializeValues(defaultValues);
2043
            data.setNew(true);
2044

    
2045
            return feature;
2046
        } catch (Exception e) {
2047
            throw new CreateFeatureException(e, getName());
2048
        }
2049
    }
2050

    
2051
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2052
        throws DataException {
2053
        type = this.fixFeatureType((DefaultFeatureType) type);
2054
        FeatureProvider data = this.provider.createFeatureProvider(type);
2055
        data.setNew(true);
2056
        if (type.hasOID() && (data.getOID() == null)) {
2057
            data.setOID(this.provider.createNewOID());
2058
        } else {
2059
            data.setOID(this.getTemporalOID());
2060
        }
2061
        return data;
2062

    
2063
    }
2064

    
2065
    @Override
2066
    public EditableFeature createNewFeature(FeatureType type,
2067
        boolean defaultValues) throws DataException {
2068
        try {
2069
            FeatureProvider data = createNewFeatureProvider(type);
2070
            DefaultEditableFeature feature =
2071
                new DefaultEditableFeature(this, data);
2072
            if (defaultValues) {
2073
                feature.initializeValues();
2074
            }
2075
            return feature;
2076
        } catch (Exception e) {
2077
            throw new CreateFeatureException(e, getName());
2078
        }
2079
    }
2080

    
2081
    @Override
2082
    public EditableFeature createNewFeature(boolean defaultValues)
2083
        throws DataException {
2084
        return this.createNewFeature(this.getDefaultFeatureType(),
2085
            defaultValues);
2086
    }
2087

    
2088
    @Override
2089
    public EditableFeature createNewFeature() throws DataException {
2090
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2091
    }
2092

    
2093
    @Override
2094
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2095
        FeatureType ft = this.getDefaultFeatureType();
2096
        EditableFeature f = this.createNewFeature(ft, false);
2097
                for( FeatureAttributeDescriptor desc : ft ) {
2098
                        try {
2099
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2100
                        } catch(Throwable th) {
2101
                                // Ignore
2102
                        }
2103
                }
2104
        return f;
2105
    }
2106

    
2107
    @Override
2108
    public EditableFeatureType createFeatureType() {
2109
        EditableFeatureType ftype = this.dataManager.createFeatureType();
2110
        return ftype;
2111
    }
2112

    
2113
    @Override
2114
    public EditableFeatureType createFeatureType(String id) {
2115
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
2116
        return ftype;
2117
    }
2118

    
2119
    //
2120
    // ====================================================================
2121
    // Index related methods
2122
    //
2123

    
2124
    @Override
2125
    public FeatureIndexes getIndexes() {
2126
        return this.indexes;
2127
    }
2128

    
2129
    @Override
2130
    public FeatureIndex createIndex(FeatureType featureType,
2131
        String attributeName, String indexName) throws DataException {
2132
        return createIndex(null, featureType, attributeName, indexName);
2133
    }
2134

    
2135
    @Override
2136
    public FeatureIndex createIndex(String indexTypeName,
2137
        FeatureType featureType, String attributeName, String indexName)
2138
        throws DataException {
2139

    
2140
        return createIndex(indexTypeName, featureType, attributeName,
2141
            indexName, false, null);
2142
    }
2143

    
2144
    @Override
2145
    public FeatureIndex createIndex(FeatureType featureType,
2146
        String attributeName, String indexName, Observer observer)
2147
        throws DataException {
2148
        return createIndex(null, featureType, attributeName, indexName,
2149
            observer);
2150
    }
2151

    
2152
    @Override
2153
    public FeatureIndex createIndex(String indexTypeName,
2154
        FeatureType featureType, String attributeName, String indexName,
2155
        final Observer observer) throws DataException {
2156

    
2157
        return createIndex(indexTypeName, featureType, attributeName,
2158
            indexName, true, observer);
2159
    }
2160

    
2161
    private FeatureIndex createIndex(String indexTypeName,
2162
        FeatureType featureType, String attributeName, String indexName,
2163
        boolean background, final Observer observer) throws DataException {
2164

    
2165
        checkNotInAppendMode();
2166
        FeatureIndexProviderServices index;
2167
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2168
                featureType, indexName,
2169
                featureType.getAttributeDescriptor(attributeName));
2170

    
2171
        try {
2172
            index.fill(background, observer);
2173
        } catch (FeatureIndexException e) {
2174
            throw new InitializeException(index.getName(), e);
2175
        }
2176

    
2177
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2178
        return index;
2179
    }
2180

    
2181
    //
2182
    // ====================================================================
2183
    // Transforms related methods
2184
    //
2185

    
2186
    @Override
2187
    public FeatureStoreTransforms getTransforms() {
2188
        return this.transforms;
2189
    }
2190

    
2191
    @Override
2192
    public FeatureQuery createFeatureQuery() {
2193
        return new DefaultFeatureQuery();
2194
    }
2195

    
2196
    @Override
2197
    public DataQuery createQuery() {
2198
        return createFeatureQuery();
2199
    }
2200

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

    
2206
    @Override
2207
    public boolean canRedo() {
2208
        return commands.canRedo();
2209
    }
2210

    
2211
    @Override
2212
    public boolean canUndo() {
2213
        return commands.canUndo();
2214
    }
2215

    
2216
    @Override
2217
    public void redo(int num) throws RedoException {
2218
        for (int i = 0; i < num; i++) {
2219
            redo();
2220
        }
2221
    }
2222

    
2223
    @Override
2224
    public void undo(int num) throws UndoException {
2225
        for (int i = 0; i < num; i++) {
2226
            undo();
2227
        }
2228
    }
2229

    
2230
    //
2231
    // ====================================================================
2232
    // Metadata related methods
2233
    //
2234

    
2235
    @Override
2236
    public Object getMetadataID() {
2237
        return this.provider.getSourceId();
2238
    }
2239

    
2240
    @Override
2241
    public void delegate(DynObject dynObject) {
2242
        this.metadata.delegate(dynObject);
2243
    }
2244

    
2245
    @Override
2246
    public DynClass getDynClass() {
2247
        return this.metadata.getDynClass();
2248
    }
2249

    
2250
    @Override
2251
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2252
                if( this.transforms.hasDynValue(name) ) {
2253
                        return this.transforms.getDynValue(name);
2254
                }
2255
                if (this.metadata.hasDynValue(name)) {
2256
                        return this.metadata.getDynValue(name);
2257
                }
2258
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2259
                        return this.provider.getProviderName();
2260
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2261
                        return this.provider.getSourceId();
2262
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2263
                        try {
2264
                                return this.getDefaultFeatureType();
2265
                        } catch (DataException e) {
2266
                                return null;
2267
                        }
2268
                }
2269
                return this.metadata.getDynValue(name);
2270
        }
2271

    
2272
    @Override
2273
    public boolean hasDynValue(String name) {
2274
                if( this.transforms.hasDynValue(name) ) {
2275
                        return true;
2276
                }
2277
        return this.metadata.hasDynValue(name);
2278
    }
2279

    
2280
    @Override
2281
    public boolean hasDynMethod(String name) {
2282
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2283
    }
2284

    
2285
    @Override
2286
    public void implement(DynClass dynClass) {
2287
        this.metadata.implement(dynClass);
2288
    }
2289

    
2290
    @Override
2291
    public Object invokeDynMethod(String name, Object[] args)
2292
        throws DynMethodException {
2293
        return this.metadata.invokeDynMethod(this, name, args);
2294
    }
2295

    
2296
    @Override
2297
    public Object invokeDynMethod(int code, Object[] args)
2298
        throws DynMethodException {
2299
        return this.metadata.invokeDynMethod(this, code, args);
2300
    }
2301

    
2302
    @Override
2303
    public void setDynValue(String name, Object value)
2304
        throws DynFieldNotFoundException {
2305
                if( this.transforms.hasDynValue(name) ) {
2306
                        this.transforms.setDynValue(name, value);
2307
                        return;
2308
                }
2309
        this.metadata.setDynValue(name, value);
2310

    
2311
    }
2312

    
2313
    /*
2314
     * (non-Javadoc)
2315
     *
2316
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2317
     */
2318
    @Override
2319
    public Set getMetadataChildren() {
2320
        return this.metadataChildren;
2321
    }
2322

    
2323
    /*
2324
     * (non-Javadoc)
2325
     *
2326
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2327
     */
2328
    @Override
2329
    public String getMetadataName() {
2330
        return this.provider.getProviderName();
2331
    }
2332

    
2333
    public FeatureTypeManager getFeatureTypeManager() {
2334
        return this.featureTypeManager;
2335
    }
2336

    
2337
    @Override
2338
    public long getFeatureCount() throws DataException {
2339
        if (featureCount == null) {
2340
            featureCount = this.provider.getFeatureCount();
2341
        }
2342
        if (this.isEditing()) {
2343
            if(this.isAppending()) {
2344
                try{
2345
                    throw new IllegalStateException();
2346
                } catch(IllegalStateException e) {
2347
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND");
2348
                    e.printStackTrace();
2349
                }
2350
                return -1;
2351
            } else {
2352
                return featureCount
2353
                    + this.featureManager.getDeltaSize();
2354
            }
2355
        }
2356
        return featureCount;
2357
    }
2358

    
2359
    private Long getTemporalOID() {
2360
        return this.temporalOid++;
2361
    }
2362

    
2363
    @Override
2364
    public FeatureType getProviderFeatureType(String featureTypeId) {
2365
        if (featureTypeId == null) {
2366
            return this.defaultFeatureType;
2367
        }
2368
        FeatureType type;
2369
        Iterator iter = this.featureTypes.iterator();
2370
        while (iter.hasNext()) {
2371
            type = (FeatureType) iter.next();
2372
            if (type.getId().equals(featureTypeId)) {
2373
                return type;
2374
            }
2375
        }
2376
        return null;
2377
    }
2378

    
2379
    @Override
2380
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2381
        return ((DefaultFeature) feature).getData();
2382
    }
2383

    
2384
    @Override
2385
    public DataStore getStore() {
2386
        return this;
2387
    }
2388

    
2389
    @Override
2390
    public FeatureStore getFeatureStore() {
2391
        return this;
2392
    }
2393

    
2394
    @Override
2395
    public void createCache(String name, DynObject parameters)
2396
        throws DataException {
2397
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2398
        if (cache == null) {
2399
            throw new CreateException("FeaureCacheProvider", null);
2400
        }
2401
        cache.apply(this, provider);
2402
        provider = cache;
2403

    
2404
        featureCount = null;
2405
    }
2406

    
2407
    @Override
2408
    public FeatureCache getCache() {
2409
        return cache;
2410
    }
2411

    
2412
    @Override
2413
    public void clear() {
2414
        if (metadata != null) {
2415
            metadata.clear();
2416
        }
2417
    }
2418

    
2419
    @Override
2420
    public String getName() {
2421
        if( this.provider != null ) {
2422
            return this.provider.getName();
2423
        }
2424
        if( this.parameters instanceof HasAFile ) {
2425
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2426
        }
2427
        return "unknow";
2428
    }
2429

    
2430
    @Override
2431
    public String getFullName() {
2432
        try {
2433
            if( this.provider!=null ) {
2434
                return this.provider.getFullName();
2435
            }
2436
            if( this.parameters instanceof HasAFile ) {
2437
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2438
            }
2439
            return null;
2440
        } catch(Throwable th) {
2441
            return null;
2442
        }
2443
    }
2444

    
2445
    @Override
2446
    public String getProviderName() {
2447
        if( this.provider!=null ) {
2448
            return this.provider.getProviderName();
2449
        }
2450
        if( this.parameters != null ) {
2451
            return this.parameters.getDataStoreName();
2452
        }
2453
        return null;
2454

    
2455
    }
2456

    
2457
    @Override
2458
    public boolean isKnownEnvelope() {
2459
        return this.provider.isKnownEnvelope();
2460
    }
2461

    
2462
    @Override
2463
    public boolean hasRetrievedFeaturesLimit() {
2464
        return this.provider.hasRetrievedFeaturesLimit();
2465
    }
2466

    
2467
    @Override
2468
    public int getRetrievedFeaturesLimit() {
2469
        return this.provider.getRetrievedFeaturesLimit();
2470
    }
2471

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

    
2480
    @Override
2481
    public Collection getTimes() {
2482
        if( this.timeSupport!=null ) {
2483
            return this.timeSupport.getTimes();
2484
        }
2485
        return this.provider.getTimes();
2486
    }
2487

    
2488
    @Override
2489
    public Collection getTimes(Interval interval) {
2490
        if( this.timeSupport!=null ) {
2491
            return this.timeSupport.getTimes(interval);
2492
        }
2493
        return this.provider.getTimes(interval);
2494
    }
2495

    
2496
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2497
        FeatureAttributeDescriptor attr;
2498
        DefaultFeatureType ft;
2499
        try {
2500
            ft = (DefaultFeatureType) this.getDefaultFeatureType();
2501
        } catch (DataException ex) {
2502
            throw new RuntimeException("Can't add time support, can't get the default feature type.", ex);
2503
        }
2504
        attr = ft.getAttributeDescriptor(timeSupport.getAttributeName());
2505
        if( attr != null ) {
2506
            throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2507
        }
2508
        attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2509
        if( attr != null ) {
2510
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2511
        }
2512
        DefaultEditableFeatureAttributeDescriptor attr2 = new DefaultEditableFeatureAttributeDescriptor();
2513
        attr2.setDataType(timeSupport.getDataType());
2514
        attr2.setIsTime(true);
2515
        attr2.setFeatureAttributeEmulator(timeSupport);
2516
        ft.add(attr2);
2517

    
2518
        this.timeSupport = timeSupport;
2519
    }
2520

    
2521
    @Override
2522
    public Object clone() throws CloneNotSupportedException {
2523

    
2524
        DataStoreParameters dsp = getParameters();
2525

    
2526
        DefaultFeatureStore cloned_store = null;
2527

    
2528
        try {
2529
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2530
                openStore(this.getProviderName(), dsp);
2531
            if (transforms != null) {
2532
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2533
                cloned_store.transforms.setStoreForClone(cloned_store);
2534
            }
2535
        } catch (Exception e) {
2536
            throw new CloneException(e);
2537
        }
2538
        return cloned_store;
2539

    
2540
    }
2541

    
2542
    @Override
2543
    public Feature getFeature(DynObject dynobject) {
2544
        if (dynobject instanceof DynObjectFeatureFacade){
2545
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2546
            return f;
2547
        }
2548
        return null;
2549
    }
2550

    
2551
    @Override
2552
    public Iterator iterator() {
2553
        try {
2554
            return this.getFeatureSet().fastIterator();
2555
        } catch (DataException ex) {
2556
            throw new RuntimeException(ex);
2557
        }
2558
    }
2559

    
2560
    @Override
2561
    public ExpressionEvaluator createExpression() {
2562
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2563
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2564
        }
2565
        return new SQLBuilderBase();
2566
    }
2567

    
2568

    
2569
    public FeatureSet features() throws DataException {
2570
        // This is to avoid jython to create a property with this name
2571
        // to access method getFeatures.
2572
        return this.getFeatureSet();
2573
    }
2574

    
2575
    @Override
2576
    public DataStoreProviderFactory getProviderFactory() {
2577
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2578
        return factory;
2579
    }
2580

    
2581
    @Override
2582
    public void useCache(String providerName, DynObject parameters) throws DataException {
2583
        throw new UnsupportedOperationException();
2584
    }
2585

    
2586
    @Override
2587
    public boolean isBroken() {
2588
        return this.state.isBroken();
2589
    }
2590

    
2591
    @Override
2592
    public Throwable getBreakingsCause() {
2593
            return this.state.getBreakingsCause();
2594
    }
2595

    
2596
    @Override
2597
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2598
//      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2599
//      if( !factory.supportNumericOID() ) {
2600
//          return null;
2601
//      }
2602
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2603
      return wrappedIndex;
2604
  }
2605
}