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

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

    
159
import org.slf4j.Logger;
160
import org.slf4j.LoggerFactory;
161

    
162
public class DefaultFeatureStore extends AbstractDisposable implements
163
    DataStoreInitializer2, FeatureStoreProviderServices, FeatureStore, Observer {
164

    
165
    private static final Logger LOG = LoggerFactory
166
        .getLogger(DefaultFeatureStore.class);
167

    
168
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
169

    
170
    private DataStoreParameters parameters = null;
171
    private FeatureSelection selection;
172
    private FeatureLocks locks;
173

    
174
    private DelegateWeakReferencingObservable delegateObservable =
175
        new DelegateWeakReferencingObservable(this);
176

    
177
    private FeatureCommandsStack commands;
178
    private FeatureTypeManager featureTypeManager;
179
    private FeatureManager featureManager;
180
    private SpatialManager spatialManager;
181

    
182
    private FeatureType defaultFeatureType = null;
183
    private List featureTypes = new ArrayList();
184

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

    
190
    private DefaultDataManager dataManager = null;
191

    
192
    private FeatureStoreProvider provider = null;
193

    
194
    private DefaultFeatureIndexes indexes;
195

    
196
    private DefaultFeatureStoreTransforms transforms;
197

    
198
    DelegatedDynObject metadata;
199

    
200
    private Set metadataChildren;
201

    
202
    private Long featureCount = null;
203

    
204
    private long temporalOid = 0;
205

    
206
    private FeatureCacheProvider cache;
207

    
208
    StateInformation state;
209

    
210
    FeatureStoreTimeSupport timeSupport;
211

    
212

    
213
    private class StateInformation extends HashMap<Object, Object> {
214

    
215
        private static final long serialVersionUID = 4109026189635185666L;
216

    
217
        private boolean broken;
218
        private Throwable breakingsCause;
219

    
220
        public StateInformation() {
221
            this.clear();
222
        }
223

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

    
231
        public boolean isBroken() {
232
            return this.broken;
233
        }
234

    
235
        public void broken() {
236
            this.broken = true;
237
        }
238

    
239
        public Throwable getBreakingsCause() {
240
            return this.breakingsCause;
241
        }
242

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

    
251

    
252

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

    
262
    public DefaultFeatureStore() {
263
        this.state = new StateInformation();
264
    }
265

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

    
270
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
271

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

    
277
        this.dataManager = (DefaultDataManager) dataManager;
278

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

    
287
    }
288

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

    
297
    @Override
298
    public DataStoreParameters getParameters() {
299
        return parameters;
300
    }
301

    
302
    public int getMode() {
303
        return this.mode;
304
    }
305

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

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

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

    
321
    public FeatureManager getFeatureManager() {
322
        return this.featureManager;
323
    }
324

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

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

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

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

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

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

    
406
        this.featureManager = null;
407
        this.spatialManager = null;
408

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

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

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

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

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

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

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

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

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

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

    
530
        }
531

    
532
        if (evaluatedAttr.isEmpty()) {
533
            evaluatedAttr = null;
534
        }
535

    
536
        state.set("evaluatedAttributes", evaluatedAttr);
537
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
538

    
539
    }
540

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

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

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

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

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

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

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

    
652
                    }
653

    
654
            }
655
        } catch(Throwable th) {
656
            state.setBreakingsCause(th);
657
        }
658

    
659

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

    
664
            if (defaultFeatureType == null ||
665
                    defaultFeatureType.getId() == null ||
666
                    !defaultFeatureType.getId().equals(defaultFeatureTypeId)) {
667

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

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

    
692
        public DataStoreProviderServices getStoreProviderServices() {
693
                return this;
694
        }
695

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

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

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

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

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

    
722
            definition.addDynFieldString("defaultFeatureTypeId")
723
                .setMandatory(true).setPersistent(true);
724
        }
725
    }
726

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

    
737
    //
738
    // ====================================================================
739
    // Gestion de la seleccion
740
    //
741

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

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

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

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

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

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

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

    
816
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
817
    }
818

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

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

    
833
    //
834
    // ====================================================================
835
    // Gestion de notificaciones
836
    //
837

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

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

    
853
    }
854

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

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

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

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

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

    
887
    //
888
    // ====================================================================
889
    // Gestion de bloqueos
890
    //
891

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

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

    
909
    //
910
    // ====================================================================
911
    // Interface Observable
912
    //
913

    
914
    @Override
915
    public void disableNotifications() {
916
        this.delegateObservable.disableNotifications();
917

    
918
    }
919

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

    
925
    @Override
926
    public void beginComplexNotification() {
927
        this.delegateObservable.beginComplexNotification();
928

    
929
    }
930

    
931
    @Override
932
    public void endComplexNotification() {
933
        this.delegateObservable.endComplexNotification();
934

    
935
    }
936

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

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

    
951
    @Override
952
    public void deleteObservers() {
953
        this.delegateObservable.deleteObservers();
954

    
955
    }
956

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

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

    
976
        } else if (observable instanceof FeatureStoreProvider) {
977
            if (observable == this.provider) {
978

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

    
987
    //
988
    // ====================================================================
989
    // Edicion
990
    //
991

    
992
    private void newVersionOfUpdate() {
993
        this.versionOfUpdate++;
994
    }
995

    
996
    private long currentVersionOfUpdate() {
997
        return this.versionOfUpdate;
998
    }
999

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

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

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

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

    
1028
        if (featureTypeManager != null) {
1029
            featureTypeManager.dispose();
1030
            featureTypeManager = null;
1031

    
1032
        }
1033

    
1034
        // TODO implementar un dispose para estos dos
1035
        featureManager = null;
1036
        spatialManager = null;
1037

    
1038
        featureCount = null;
1039

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

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

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

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

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

    
1102
    private void invalidateIndexes() {
1103
        setIndexesValidStatus(false);
1104
    }
1105

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1223
    private static EditableFeature lastChangedFeature = null;
1224

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

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

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

    
1259
    synchronized public void doInsert(EditableFeature feature)
1260
        throws DataException {
1261
        checkIsOwnFeature(feature);
1262

    
1263
        waitForIndexes();
1264

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

    
1277

    
1278
        featureManager.add(newFeature);
1279
        spatialManager.insertFeature(newFeature);
1280

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1538
        case MODE_APPEND:
1539
                return true;
1540

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

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

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

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

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

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

    
1591
            }
1592
            explorer.add(provider, params, true);
1593

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

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

    
1629
    //
1630
    // ====================================================================
1631
    // Obtencion de datos
1632
    // getDataCollection, getFeatureCollection
1633
    //
1634

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

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

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

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

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

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

    
1677
    @Override
1678
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1679
        try {
1680
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1681
            return pager.asList();
1682
        } catch (BaseException ex) {
1683
            throw new RuntimeException("Can't create the list of features.", ex);
1684
        }
1685
    }
1686

    
1687
    @Override
1688
    public List<Feature> getFeatures() {
1689
        return this.getFeatures(null, 500);
1690
    }
1691

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

    
1702
    @Override
1703
    public void accept(Visitor visitor, DataQuery dataQuery)
1704
        throws BaseException {
1705
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1706
        try {
1707
            set.accept(visitor);
1708
        } finally {
1709
            set.dispose();
1710
        }
1711
    }
1712

    
1713
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1714
        throws DataException {
1715
        DefaultFeatureType fType =
1716
            (DefaultFeatureType) this.getFeatureType(featureQuery
1717
                .getFeatureTypeId());
1718
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1719
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1720
        }
1721
        return fType;
1722
    }
1723

    
1724
    @Override
1725
    public void getFeatureSet(Observer observer) throws DataException {
1726
        checkNotInAppendMode();
1727
        this.getFeatureSet(null, observer);
1728
    }
1729

    
1730
    @Override
1731
    public void getFeatureSet(FeatureQuery query, Observer observer)
1732
        throws DataException {
1733
        class LoadInBackGround implements Runnable {
1734

    
1735
            private final FeatureStore store;
1736
            private final FeatureQuery query;
1737
            private final Observer observer;
1738

    
1739
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1740
                Observer observer) {
1741
                this.store = store;
1742
                this.query = query;
1743
                this.observer = observer;
1744
            }
1745

    
1746
            void notify(FeatureStoreNotification theNotification) {
1747
                observer.update(store, theNotification);
1748
            }
1749

    
1750
            @Override
1751
            public void run() {
1752
                FeatureSet set = null;
1753
                try {
1754
                    set = store.getFeatureSet(query);
1755
                    notify(new DefaultFeatureStoreNotification(store,
1756
                        FeatureStoreNotification.LOAD_FINISHED, set));
1757
                } catch (Exception e) {
1758
                    notify(new DefaultFeatureStoreNotification(store,
1759
                        FeatureStoreNotification.LOAD_FINISHED, e));
1760
                } finally {
1761
                    dispose(set);
1762
                }
1763
            }
1764
        }
1765

    
1766
        checkNotInAppendMode();
1767
        if (query == null) {
1768
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1769
        }
1770
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1771
        Thread thread = new Thread(task, "Load Feature Set in background");
1772
        thread.start();
1773
    }
1774

    
1775
    @Override
1776
    public Feature getFeatureByReference(FeatureReference reference)
1777
        throws DataException {
1778
        checkNotInAppendMode();
1779
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1780
        FeatureType featureType;
1781
        if (ref.getFeatureTypeId() == null) {
1782
            featureType = this.getDefaultFeatureType();
1783
        } else {
1784
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1785
        }
1786
        return this.getFeatureByReference(reference, featureType);
1787
    }
1788

    
1789
    @Override
1790
    public Feature getFeatureByReference(FeatureReference reference,
1791
        FeatureType featureType) throws DataException {
1792
        checkNotInAppendMode();
1793
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1794
        if (this.mode == MODE_FULLEDIT) {
1795
            Feature f = featureManager.get(reference, this, featureType);
1796
            if (f != null) {
1797
                return f;
1798
            }
1799
        }
1800

    
1801
        FeatureType sourceFeatureType = featureType;
1802
        if (!this.transforms.isEmpty()) {
1803
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1804
        }
1805
        // TODO comprobar que el id es de este store
1806

    
1807
        DefaultFeature feature =
1808
            new DefaultFeature(this,
1809
                this.provider.getFeatureProviderByReference(
1810
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1811

    
1812
        if (!this.transforms.isEmpty()) {
1813
            return this.transforms.applyTransform(feature, featureType);
1814
        }
1815
        return feature;
1816
    }
1817

    
1818
    //
1819
    // ====================================================================
1820
    // Gestion de features
1821
    //
1822

    
1823
    private FeatureType fixFeatureType(DefaultFeatureType type)
1824
        throws DataException {
1825
        FeatureType original = this.getDefaultFeatureType();
1826

    
1827
        if ((type == null) || type.equals(original)) {
1828
            return original;
1829
        } else {
1830
            if (!type.isSubtypeOf(original)) {
1831
                Iterator iter = this.getFeatureTypes().iterator();
1832
                FeatureType tmpType;
1833
                boolean found = false;
1834
                while (iter.hasNext()) {
1835
                    tmpType = (FeatureType) iter.next();
1836
                    if (type.equals(tmpType)) {
1837
                        return type;
1838

    
1839
                    } else
1840
                        if (type.isSubtypeOf(tmpType)) {
1841
                            found = true;
1842
                            original = tmpType;
1843
                            break;
1844
                        }
1845

    
1846
                }
1847
                if (!found) {
1848
                    throw new IllegalFeatureTypeException(getName());
1849
                }
1850
            }
1851
        }
1852

    
1853
        // Checks that type has all fields of pk
1854
        // else add the missing attributes at the end.
1855
        if (!original.hasOID()) {
1856
            // Gets original pk attributes
1857
            DefaultEditableFeatureType edOriginal =
1858
                (DefaultEditableFeatureType) original.getEditable();
1859
            FeatureAttributeDescriptor orgAttr;
1860
            Iterator edOriginalIter = edOriginal.iterator();
1861
            while (edOriginalIter.hasNext()) {
1862
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1863
                if (!orgAttr.isPrimaryKey()) {
1864
                    edOriginalIter.remove();
1865
                }
1866
            }
1867

    
1868
            // Checks if all pk attributes are in type
1869
            Iterator typeIterator;
1870
            edOriginalIter = edOriginal.iterator();
1871
            FeatureAttributeDescriptor attr;
1872
            while (edOriginalIter.hasNext()) {
1873
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1874
                typeIterator = type.iterator();
1875
                while (typeIterator.hasNext()) {
1876
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1877
                    if (attr.getName().equals(orgAttr.getName())) {
1878
                        edOriginalIter.remove();
1879
                        break;
1880
                    }
1881
                }
1882
            }
1883

    
1884
            // add missing pk attributes if any
1885
            if (edOriginal.size() > 0) {
1886
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1887
                DefaultEditableFeatureType edType =
1888
                    (DefaultEditableFeatureType) original.getEditable();
1889
                edType.clear();
1890
                edType.addAll(type);
1891
                edType.addAll(edOriginal);
1892
                if (!isEditable) {
1893
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1894
                }
1895
            }
1896

    
1897
        }
1898

    
1899
        return type;
1900
    }
1901

    
1902
    @Override
1903
    public void validateFeatures(int mode) throws DataException {
1904
        FeatureSet collection = null;
1905
        DisposableIterator iter = null;
1906
        try {
1907
            checkNotInAppendMode();
1908
            collection = this.getFeatureSet();
1909
            iter = collection.fastIterator();
1910
            long previousVersionOfUpdate = currentVersionOfUpdate();
1911
            while (iter.hasNext()) {
1912
                ((DefaultFeature) iter.next()).validate(mode);
1913
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1914
                    throw new ConcurrentDataModificationException(getName());
1915
                }
1916
            }
1917
        } catch (Exception e) {
1918
            throw new ValidateFeaturesException(e, getName());
1919
        } finally {
1920
            dispose(iter);
1921
            dispose(collection);
1922
        }
1923
    }
1924

    
1925
    @Override
1926
    public FeatureType getDefaultFeatureType() throws DataException {
1927
        try {
1928

    
1929
            if (isEditing()) {
1930
                FeatureType auxFeatureType =
1931
                    featureTypeManager.getType(defaultFeatureType.getId());
1932
                if (auxFeatureType != null) {
1933
                    return avoidEditable(auxFeatureType);
1934
                }
1935
            }
1936
            FeatureType type = this.transforms.getDefaultFeatureType();
1937
            if (type != null) {
1938
                return avoidEditable(type);
1939
            }
1940

    
1941
            return avoidEditable(defaultFeatureType);
1942

    
1943
        } catch (Exception e) {
1944
            throw new GetFeatureTypeException(e, getName());
1945
        }
1946
    }
1947

    
1948
    private FeatureType avoidEditable(FeatureType ft) {
1949
        if (ft instanceof EditableFeatureType) {
1950
            return ((EditableFeatureType) ft).getNotEditableCopy();
1951
        } else {
1952
            return ft;
1953
        }
1954
    }
1955

    
1956
    @Override
1957
    public FeatureType getFeatureType(String featureTypeId)
1958
        throws DataException {
1959
        if (featureTypeId == null) {
1960
            return this.getDefaultFeatureType();
1961
        }
1962
        try {
1963
            if (isEditing()) {
1964
                FeatureType auxFeatureType =
1965
                    featureTypeManager.getType(featureTypeId);
1966
                if (auxFeatureType != null) {
1967
                    return auxFeatureType;
1968
                }
1969
            }
1970
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1971
            if (type != null) {
1972
                return type;
1973
            }
1974
            Iterator iter = this.featureTypes.iterator();
1975
            while (iter.hasNext()) {
1976
                type = (FeatureType) iter.next();
1977
                if (type.getId().equals(featureTypeId)) {
1978
                    return type;
1979
                }
1980
            }
1981
            return null;
1982
        } catch (Exception e) {
1983
            throw new GetFeatureTypeException(e, getName());
1984
        }
1985
    }
1986

    
1987
    public FeatureType getProviderDefaultFeatureType() {
1988
        return defaultFeatureType;
1989
    }
1990

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

    
2025
    public List getProviderFeatureTypes() throws DataException {
2026
        return Collections.unmodifiableList(this.featureTypes);
2027
    }
2028

    
2029
    @Override
2030
    public Feature createFeature(FeatureProvider data) throws DataException {
2031
        DefaultFeature feature = new DefaultFeature(this, data);
2032
        return feature;
2033
    }
2034

    
2035
    public Feature createFeature(FeatureProvider data, FeatureType type)
2036
        throws DataException {
2037
        // FIXME: falta por implementar
2038
        // Comprobar si es un subtipo del feature de data
2039
        // y construir un feature usando el subtipo.
2040
        // Probablemente requiera generar una copia del data.
2041
        throw new NotYetImplemented();
2042
    }
2043

    
2044
    @Override
2045
    public EditableFeature createNewFeature(FeatureType type,
2046
        Feature defaultValues) throws DataException {
2047
        try {
2048
            FeatureProvider data = createNewFeatureProvider(type);
2049
            DefaultEditableFeature feature =
2050
                new DefaultEditableFeature(this, data);
2051
            feature.initializeValues(defaultValues);
2052
            data.setNew(true);
2053

    
2054
            return feature;
2055
        } catch (Exception e) {
2056
            throw new CreateFeatureException(e, getName());
2057
        }
2058
    }
2059

    
2060
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2061
        throws DataException {
2062
        type = this.fixFeatureType((DefaultFeatureType) type);
2063
        FeatureProvider data = this.provider.createFeatureProvider(type);
2064
        data.setNew(true);
2065
        if (type.hasOID() && (data.getOID() == null)) {
2066
            data.setOID(this.provider.createNewOID());
2067
        } else {
2068
            data.setOID(this.getTemporalOID());
2069
        }
2070
        return data;
2071

    
2072
    }
2073

    
2074
    @Override
2075
    public EditableFeature createNewFeature(FeatureType type,
2076
        boolean defaultValues) throws DataException {
2077
        try {
2078
            FeatureProvider data = createNewFeatureProvider(type);
2079
            DefaultEditableFeature feature =
2080
                new DefaultEditableFeature(this, data);
2081
            if (defaultValues) {
2082
                feature.initializeValues();
2083
            }
2084
            return feature;
2085
        } catch (Exception e) {
2086
            throw new CreateFeatureException(e, getName());
2087
        }
2088
    }
2089

    
2090
    @Override
2091
    public EditableFeature createNewFeature(boolean defaultValues)
2092
        throws DataException {
2093
        return this.createNewFeature(this.getDefaultFeatureType(),
2094
            defaultValues);
2095
    }
2096

    
2097
    @Override
2098
    public EditableFeature createNewFeature() throws DataException {
2099
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2100
    }
2101

    
2102
    @Override
2103
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2104
        FeatureType ft = this.getDefaultFeatureType();
2105
        EditableFeature f = this.createNewFeature(ft, false);
2106
                for( FeatureAttributeDescriptor desc : ft ) {
2107
                        try {
2108
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2109
                        } catch(Throwable th) {
2110
                                // Ignore
2111
                        }
2112
                }
2113
        return f;
2114
    }
2115

    
2116
    @Override
2117
    public EditableFeatureType createFeatureType() {
2118
        EditableFeatureType ftype = this.dataManager.createFeatureType();
2119
        return ftype;
2120
    }
2121

    
2122
    @Override
2123
    public EditableFeatureType createFeatureType(String id) {
2124
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
2125
        return ftype;
2126
    }
2127

    
2128
    //
2129
    // ====================================================================
2130
    // Index related methods
2131
    //
2132

    
2133
    @Override
2134
    public FeatureIndexes getIndexes() {
2135
        return this.indexes;
2136
    }
2137

    
2138
    @Override
2139
    public FeatureIndex createIndex(FeatureType featureType,
2140
        String attributeName, String indexName) throws DataException {
2141
        return createIndex(null, featureType, attributeName, indexName);
2142
    }
2143

    
2144
    @Override
2145
    public FeatureIndex createIndex(String indexTypeName,
2146
        FeatureType featureType, String attributeName, String indexName)
2147
        throws DataException {
2148

    
2149
        return createIndex(indexTypeName, featureType, attributeName,
2150
            indexName, false, null);
2151
    }
2152

    
2153
    @Override
2154
    public FeatureIndex createIndex(FeatureType featureType,
2155
        String attributeName, String indexName, Observer observer)
2156
        throws DataException {
2157
        return createIndex(null, featureType, attributeName, indexName,
2158
            observer);
2159
    }
2160

    
2161
    @Override
2162
    public FeatureIndex createIndex(String indexTypeName,
2163
        FeatureType featureType, String attributeName, String indexName,
2164
        final Observer observer) throws DataException {
2165

    
2166
        return createIndex(indexTypeName, featureType, attributeName,
2167
            indexName, true, observer);
2168
    }
2169

    
2170
    private FeatureIndex createIndex(String indexTypeName,
2171
        FeatureType featureType, String attributeName, String indexName,
2172
        boolean background, final Observer observer) throws DataException {
2173

    
2174
        checkNotInAppendMode();
2175
        FeatureIndexProviderServices index;
2176
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2177
                featureType, indexName,
2178
                featureType.getAttributeDescriptor(attributeName));
2179

    
2180
        try {
2181
            index.fill(background, observer);
2182
        } catch (FeatureIndexException e) {
2183
            throw new InitializeException(index.getName(), e);
2184
        }
2185

    
2186
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2187
        return index;
2188
    }
2189

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

    
2195
    @Override
2196
    public FeatureStoreTransforms getTransforms() {
2197
        return this.transforms;
2198
    }
2199

    
2200
    @Override
2201
    public FeatureQuery createFeatureQuery() {
2202
        return new DefaultFeatureQuery();
2203
    }
2204

    
2205
    @Override
2206
    public DataQuery createQuery() {
2207
        return createFeatureQuery();
2208
    }
2209

    
2210
    //
2211
    // ====================================================================
2212
    // UndoRedo related methods
2213
    //
2214

    
2215
    @Override
2216
    public boolean canRedo() {
2217
        return commands.canRedo();
2218
    }
2219

    
2220
    @Override
2221
    public boolean canUndo() {
2222
        return commands.canUndo();
2223
    }
2224

    
2225
    @Override
2226
    public void redo(int num) throws RedoException {
2227
        for (int i = 0; i < num; i++) {
2228
            redo();
2229
        }
2230
    }
2231

    
2232
    @Override
2233
    public void undo(int num) throws UndoException {
2234
        for (int i = 0; i < num; i++) {
2235
            undo();
2236
        }
2237
    }
2238

    
2239
    //
2240
    // ====================================================================
2241
    // Metadata related methods
2242
    //
2243

    
2244
    @Override
2245
    public Object getMetadataID() {
2246
        return this.provider.getSourceId();
2247
    }
2248

    
2249
    @Override
2250
    public void delegate(DynObject dynObject) {
2251
        this.metadata.delegate(dynObject);
2252
    }
2253

    
2254
    @Override
2255
    public DynClass getDynClass() {
2256
        return this.metadata.getDynClass();
2257
    }
2258

    
2259
    @Override
2260
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2261
                if( this.transforms.hasDynValue(name) ) {
2262
                        return this.transforms.getDynValue(name);
2263
                }
2264
                if (this.metadata.hasDynValue(name)) {
2265
                        return this.metadata.getDynValue(name);
2266
                }
2267
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2268
                        return this.provider.getProviderName();
2269
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2270
                        return this.provider.getSourceId();
2271
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2272
                        try {
2273
                                return this.getDefaultFeatureType();
2274
                        } catch (DataException e) {
2275
                                return null;
2276
                        }
2277
                }
2278
                return this.metadata.getDynValue(name);
2279
        }
2280

    
2281
    @Override
2282
    public boolean hasDynValue(String name) {
2283
                if( this.transforms.hasDynValue(name) ) {
2284
                        return true;
2285
                }
2286
        return this.metadata.hasDynValue(name);
2287
    }
2288

    
2289
    @Override
2290
    public boolean hasDynMethod(String name) {
2291
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2292
    }
2293

    
2294
    @Override
2295
    public void implement(DynClass dynClass) {
2296
        this.metadata.implement(dynClass);
2297
    }
2298

    
2299
    @Override
2300
    public Object invokeDynMethod(String name, Object[] args)
2301
        throws DynMethodException {
2302
        return this.metadata.invokeDynMethod(this, name, args);
2303
    }
2304

    
2305
    @Override
2306
    public Object invokeDynMethod(int code, Object[] args)
2307
        throws DynMethodException {
2308
        return this.metadata.invokeDynMethod(this, code, args);
2309
    }
2310

    
2311
    @Override
2312
    public void setDynValue(String name, Object value)
2313
        throws DynFieldNotFoundException {
2314
                if( this.transforms.hasDynValue(name) ) {
2315
                        this.transforms.setDynValue(name, value);
2316
                        return;
2317
                }
2318
        this.metadata.setDynValue(name, value);
2319

    
2320
    }
2321

    
2322
    /*
2323
     * (non-Javadoc)
2324
     *
2325
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2326
     */
2327
    @Override
2328
    public Set getMetadataChildren() {
2329
        return this.metadataChildren;
2330
    }
2331

    
2332
    /*
2333
     * (non-Javadoc)
2334
     *
2335
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2336
     */
2337
    @Override
2338
    public String getMetadataName() {
2339
        return this.provider.getProviderName();
2340
    }
2341

    
2342
    public FeatureTypeManager getFeatureTypeManager() {
2343
        return this.featureTypeManager;
2344
    }
2345

    
2346
    @Override
2347
    public long getFeatureCount() throws DataException {
2348
        if (featureCount == null) {
2349
            featureCount = this.provider.getFeatureCount();
2350
        }
2351
        if (this.isEditing()) {
2352
            if(this.isAppending()) {
2353
                try{
2354
                    throw new IllegalStateException();
2355
                } catch(IllegalStateException e) {
2356
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND");
2357
                    e.printStackTrace();
2358
                }
2359
                return -1;
2360
            } else {
2361
                return featureCount
2362
                    + this.featureManager.getDeltaSize();
2363
            }
2364
        }
2365
        return featureCount;
2366
    }
2367

    
2368
    private Long getTemporalOID() {
2369
        return this.temporalOid++;
2370
    }
2371

    
2372
    @Override
2373
    public FeatureType getProviderFeatureType(String featureTypeId) {
2374
        if (featureTypeId == null) {
2375
            return this.defaultFeatureType;
2376
        }
2377
        FeatureType type;
2378
        Iterator iter = this.featureTypes.iterator();
2379
        while (iter.hasNext()) {
2380
            type = (FeatureType) iter.next();
2381
            if (type.getId().equals(featureTypeId)) {
2382
                return type;
2383
            }
2384
        }
2385
        return null;
2386
    }
2387

    
2388
    @Override
2389
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2390
        return ((DefaultFeature) feature).getData();
2391
    }
2392

    
2393
    @Override
2394
    public DataStore getStore() {
2395
        return this;
2396
    }
2397

    
2398
    @Override
2399
    public FeatureStore getFeatureStore() {
2400
        return this;
2401
    }
2402

    
2403
    @Override
2404
    public void createCache(String name, DynObject parameters)
2405
        throws DataException {
2406
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2407
        if (cache == null) {
2408
            throw new CreateException("FeaureCacheProvider", null);
2409
        }
2410
        cache.apply(this, provider);
2411
        provider = cache;
2412

    
2413
        featureCount = null;
2414
    }
2415

    
2416
    @Override
2417
    public FeatureCache getCache() {
2418
        return cache;
2419
    }
2420

    
2421
    @Override
2422
    public void clear() {
2423
        if (metadata != null) {
2424
            metadata.clear();
2425
        }
2426
    }
2427

    
2428
    @Override
2429
    public String getName() {
2430
        if( this.provider != null ) {
2431
            return this.provider.getName();
2432
        }
2433
        if( this.parameters instanceof HasAFile ) {
2434
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2435
        }
2436
        return "unknow";
2437
    }
2438

    
2439
    @Override
2440
    public String getFullName() {
2441
        try {
2442
            if( this.provider!=null ) {
2443
                return this.provider.getFullName();
2444
            }
2445
            if( this.parameters instanceof HasAFile ) {
2446
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2447
            }
2448
            return null;
2449
        } catch(Throwable th) {
2450
            return null;
2451
        }
2452
    }
2453

    
2454
    @Override
2455
    public String getProviderName() {
2456
        if( this.provider!=null ) {
2457
            return this.provider.getProviderName();
2458
        }
2459
        if( this.parameters != null ) {
2460
            return this.parameters.getDataStoreName();
2461
        }
2462
        return null;
2463

    
2464
    }
2465

    
2466
    @Override
2467
    public boolean isKnownEnvelope() {
2468
        return this.provider.isKnownEnvelope();
2469
    }
2470

    
2471
    @Override
2472
    public boolean hasRetrievedFeaturesLimit() {
2473
        return this.provider.hasRetrievedFeaturesLimit();
2474
    }
2475

    
2476
    @Override
2477
    public int getRetrievedFeaturesLimit() {
2478
        return this.provider.getRetrievedFeaturesLimit();
2479
    }
2480

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

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

    
2497
    @Override
2498
    public Collection getTimes(Interval interval) {
2499
        if( this.timeSupport!=null ) {
2500
            return this.timeSupport.getTimes(interval);
2501
        }
2502
        return this.provider.getTimes(interval);
2503
    }
2504

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

    
2527
        this.timeSupport = timeSupport;
2528
    }
2529

    
2530
    @Override
2531
    public Object clone() throws CloneNotSupportedException {
2532

    
2533
        DataStoreParameters dsp = getParameters();
2534

    
2535
        DefaultFeatureStore cloned_store = null;
2536

    
2537
        try {
2538
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2539
                openStore(this.getProviderName(), dsp);
2540
            if (transforms != null) {
2541
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2542
                cloned_store.transforms.setStoreForClone(cloned_store);
2543
            }
2544
        } catch (Exception e) {
2545
            throw new CloneException(e);
2546
        }
2547
        return cloned_store;
2548

    
2549
    }
2550

    
2551
    @Override
2552
    public Feature getFeature(DynObject dynobject) {
2553
        if (dynobject instanceof DynObjectFeatureFacade){
2554
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2555
            return f;
2556
        }
2557
        return null;
2558
    }
2559

    
2560
    @Override
2561
    public Iterator iterator() {
2562
        try {
2563
            return this.getFeatureSet().fastIterator();
2564
        } catch (DataException ex) {
2565
            throw new RuntimeException(ex);
2566
        }
2567
    }
2568

    
2569
    @Override
2570
    public ExpressionBuilder createExpressionBuilder() {
2571
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2572
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2573
        }
2574
        return new SQLBuilderBase();
2575
    }
2576

    
2577
    @Override
2578
    public ExpressionBuilder createExpression() {
2579
        return createExpressionBuilder();
2580
    }
2581

    
2582
    public FeatureSet features() throws DataException {
2583
        // This is to avoid jython to create a property with this name
2584
        // to access method getFeatures.
2585
        return this.getFeatureSet();
2586
    }
2587

    
2588
    @Override
2589
    public DataStoreProviderFactory getProviderFactory() {
2590
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2591
        return factory;
2592
    }
2593

    
2594
    @Override
2595
    public void useCache(String providerName, DynObject parameters) throws DataException {
2596
        throw new UnsupportedOperationException();
2597
    }
2598

    
2599
    @Override
2600
    public boolean isBroken() {
2601
        return this.state.isBroken();
2602
    }
2603

    
2604
    @Override
2605
    public Throwable getBreakingsCause() {
2606
            return this.state.getBreakingsCause();
2607
    }
2608

    
2609
    @Override
2610
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2611
//      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2612
//      if( !factory.supportNumericOID() ) {
2613
//          return null;
2614
//      }
2615
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2616
      return wrappedIndex;
2617
  }
2618
}