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

History | View | Annotate | Download (87.3 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
191
    private DefaultDataManager dataManager = null;
192

    
193
    private FeatureStoreProvider provider = null;
194

    
195
    private DefaultFeatureIndexes indexes;
196

    
197
    private DefaultFeatureStoreTransforms transforms;
198

    
199
    DelegatedDynObject metadata;
200

    
201
    private Set metadataChildren;
202

    
203
    private Long featureCount = null;
204

    
205
    private long temporalOid = 0;
206

    
207
    private FeatureCacheProvider cache;
208

    
209
    StateInformation state;
210

    
211
    FeatureStoreTimeSupport timeSupport;
212

    
213

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

    
216
        private static final long serialVersionUID = 4109026189635185666L;
217

    
218
        private boolean broken;
219
        private Throwable breakingsCause;
220

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

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

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

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

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

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

    
252

    
253

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

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

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

    
271
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
272

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

    
278
        this.dataManager = (DefaultDataManager) dataManager;
279

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

    
288
    }
289

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
531
        }
532

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

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

    
540
    }
541

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

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

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

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

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

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

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

    
653
                    }
654

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

    
660

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
854
    }
855

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

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

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

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

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

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

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

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

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

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

    
919
    }
920

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

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

    
930
    }
931

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

    
936
    }
937

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

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

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

    
956
    }
957

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

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

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

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

    
988
    //
989
    // ====================================================================
990
    // Edicion
991
    //
992

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

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

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

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

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

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

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

    
1033
        }
1034

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

    
1039
        featureCount = null;
1040

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1224
    private static EditableFeature lastChangedFeature = null;
1225

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

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

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

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

    
1264
        waitForIndexes();
1265

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

    
1278

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1539
        case MODE_APPEND:
1540
                return true;
1541

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1688
    @Override
1689
    public FeatureSet getFeatureSet(String filter, String sortBy, boolean asc) throws DataException {
1690
        FeatureQuery query = this.createFeatureQuery();
1691
        if( !StringUtils.isEmpty(filter) ) {
1692
            query.setFilter(filter);
1693
        }
1694
        if( !StringUtils.isEmpty(sortBy) ) {
1695
            query.getOrder().add(sortBy, asc);
1696
        }
1697
        return this.getFeatureSet(query);
1698
    }
1699

    
1700
    @Override
1701
    public List<Feature> getFeatures(FeatureQuery query)  {
1702
        return this.getFeatures(query, 100);
1703
    }
1704
    
1705
    @Override
1706
    public List<Feature> getFeatures(FeatureQuery query, int pageSize)  {
1707
        try {
1708
            FeaturePagingHelper pager = this.dataManager.createFeaturePagingHelper(this, query, pageSize);
1709
            return pager.asList();
1710
        } catch (BaseException ex) {
1711
            throw new RuntimeException("Can't create the list of features.", ex);
1712
        }
1713
    }
1714

    
1715
    @Override
1716
    public List<Feature> getFeatures() {
1717
        return this.getFeatures(null, 500);
1718
    }
1719

    
1720
    @Override
1721
    public void accept(Visitor visitor) throws BaseException {
1722
        FeatureSet set = getFeatureSet();
1723
        try {
1724
            set.accept(visitor);
1725
        } finally {
1726
            set.dispose();
1727
        }
1728
    }
1729

    
1730
    @Override
1731
    public void accept(Visitor visitor, DataQuery dataQuery)
1732
        throws BaseException {
1733
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1734
        try {
1735
            set.accept(visitor);
1736
        } finally {
1737
            set.dispose();
1738
        }
1739
    }
1740

    
1741
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1742
        throws DataException {
1743
        DefaultFeatureType fType =
1744
            (DefaultFeatureType) this.getFeatureType(featureQuery
1745
                .getFeatureTypeId());
1746
        if( featureQuery.hasAttributeNames() || featureQuery.hasConstantsAttributeNames() ) {
1747
            return fType.getSubtype(featureQuery.getAttributeNames(), featureQuery.getConstantsAttributeNames() );
1748
        }
1749
        return fType;
1750
    }
1751

    
1752
    @Override
1753
    public void getFeatureSet(Observer observer) throws DataException {
1754
        checkNotInAppendMode();
1755
        this.getFeatureSet(null, observer);
1756
    }
1757

    
1758
    @Override
1759
    public void getFeatureSet(FeatureQuery query, Observer observer)
1760
        throws DataException {
1761
        class LoadInBackGround implements Runnable {
1762

    
1763
            private final FeatureStore store;
1764
            private final FeatureQuery query;
1765
            private final Observer observer;
1766

    
1767
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1768
                Observer observer) {
1769
                this.store = store;
1770
                this.query = query;
1771
                this.observer = observer;
1772
            }
1773

    
1774
            void notify(FeatureStoreNotification theNotification) {
1775
                observer.update(store, theNotification);
1776
            }
1777

    
1778
            @Override
1779
            public void run() {
1780
                FeatureSet set = null;
1781
                try {
1782
                    set = store.getFeatureSet(query);
1783
                    notify(new DefaultFeatureStoreNotification(store,
1784
                        FeatureStoreNotification.LOAD_FINISHED, set));
1785
                } catch (Exception e) {
1786
                    notify(new DefaultFeatureStoreNotification(store,
1787
                        FeatureStoreNotification.LOAD_FINISHED, e));
1788
                } finally {
1789
                    dispose(set);
1790
                }
1791
            }
1792
        }
1793

    
1794
        checkNotInAppendMode();
1795
        if (query == null) {
1796
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1797
        }
1798
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1799
        Thread thread = new Thread(task, "Load Feature Set in background");
1800
        thread.start();
1801
    }
1802

    
1803
    @Override
1804
    public Feature getFeatureByReference(FeatureReference reference)
1805
        throws DataException {
1806
        checkNotInAppendMode();
1807
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1808
        FeatureType featureType;
1809
        if (ref.getFeatureTypeId() == null) {
1810
            featureType = this.getDefaultFeatureType();
1811
        } else {
1812
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1813
        }
1814
        return this.getFeatureByReference(reference, featureType);
1815
    }
1816

    
1817
    @Override
1818
    public Feature getFeatureByReference(FeatureReference reference,
1819
        FeatureType featureType) throws DataException {
1820
        checkNotInAppendMode();
1821
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1822
        if (this.mode == MODE_FULLEDIT) {
1823
            Feature f = featureManager.get(reference, this, featureType);
1824
            if (f != null) {
1825
                return f;
1826
            }
1827
        }
1828

    
1829
        FeatureType sourceFeatureType = featureType;
1830
        if (!this.transforms.isEmpty()) {
1831
            sourceFeatureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1832
        }
1833
        // TODO comprobar que el id es de este store
1834

    
1835
        DefaultFeature feature =
1836
            new DefaultFeature(this,
1837
                this.provider.getFeatureProviderByReference(
1838
                    (FeatureReferenceProviderServices) reference, sourceFeatureType));
1839

    
1840
        if (!this.transforms.isEmpty()) {
1841
            return this.transforms.applyTransform(feature, featureType);
1842
        }
1843
        return feature;
1844
    }
1845

    
1846
    //
1847
    // ====================================================================
1848
    // Gestion de features
1849
    //
1850

    
1851
    private FeatureType fixFeatureType(DefaultFeatureType type)
1852
        throws DataException {
1853
        FeatureType original = this.getDefaultFeatureType();
1854

    
1855
        if ((type == null) || type.equals(original)) {
1856
            return original;
1857
        } else {
1858
            if (!type.isSubtypeOf(original)) {
1859
                Iterator iter = this.getFeatureTypes().iterator();
1860
                FeatureType tmpType;
1861
                boolean found = false;
1862
                while (iter.hasNext()) {
1863
                    tmpType = (FeatureType) iter.next();
1864
                    if (type.equals(tmpType)) {
1865
                        return type;
1866

    
1867
                    } else
1868
                        if (type.isSubtypeOf(tmpType)) {
1869
                            found = true;
1870
                            original = tmpType;
1871
                            break;
1872
                        }
1873

    
1874
                }
1875
                if (!found) {
1876
                    throw new IllegalFeatureTypeException(getName());
1877
                }
1878
            }
1879
        }
1880

    
1881
        // Checks that type has all fields of pk
1882
        // else add the missing attributes at the end.
1883
        if (!original.hasOID()) {
1884
            // Gets original pk attributes
1885
            DefaultEditableFeatureType edOriginal =
1886
                (DefaultEditableFeatureType) original.getEditable();
1887
            FeatureAttributeDescriptor orgAttr;
1888
            Iterator edOriginalIter = edOriginal.iterator();
1889
            while (edOriginalIter.hasNext()) {
1890
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1891
                if (!orgAttr.isPrimaryKey()) {
1892
                    edOriginalIter.remove();
1893
                }
1894
            }
1895

    
1896
            // Checks if all pk attributes are in type
1897
            Iterator typeIterator;
1898
            edOriginalIter = edOriginal.iterator();
1899
            FeatureAttributeDescriptor attr;
1900
            while (edOriginalIter.hasNext()) {
1901
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1902
                typeIterator = type.iterator();
1903
                while (typeIterator.hasNext()) {
1904
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1905
                    if (attr.getName().equals(orgAttr.getName())) {
1906
                        edOriginalIter.remove();
1907
                        break;
1908
                    }
1909
                }
1910
            }
1911

    
1912
            // add missing pk attributes if any
1913
            if (edOriginal.size() > 0) {
1914
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1915
                DefaultEditableFeatureType edType =
1916
                    (DefaultEditableFeatureType) original.getEditable();
1917
                edType.clear();
1918
                edType.addAll(type);
1919
                edType.addAll(edOriginal);
1920
                if (!isEditable) {
1921
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1922
                }
1923
            }
1924

    
1925
        }
1926

    
1927
        return type;
1928
    }
1929

    
1930
    @Override
1931
    public void validateFeatures(int mode) throws DataException {
1932
        FeatureSet collection = null;
1933
        DisposableIterator iter = null;
1934
        try {
1935
            checkNotInAppendMode();
1936
            collection = this.getFeatureSet();
1937
            iter = collection.fastIterator();
1938
            long previousVersionOfUpdate = currentVersionOfUpdate();
1939
            while (iter.hasNext()) {
1940
                ((DefaultFeature) iter.next()).validate(mode);
1941
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1942
                    throw new ConcurrentDataModificationException(getName());
1943
                }
1944
            }
1945
        } catch (Exception e) {
1946
            throw new ValidateFeaturesException(e, getName());
1947
        } finally {
1948
            dispose(iter);
1949
            dispose(collection);
1950
        }
1951
    }
1952

    
1953
    @Override
1954
    public FeatureType getDefaultFeatureType() throws DataException {
1955
        try {
1956

    
1957
            if (isEditing()) {
1958
                FeatureType auxFeatureType =
1959
                    featureTypeManager.getType(defaultFeatureType.getId());
1960
                if (auxFeatureType != null) {
1961
                    return avoidEditable(auxFeatureType);
1962
                }
1963
            }
1964
            FeatureType type = this.transforms.getDefaultFeatureType();
1965
            if (type != null) {
1966
                return avoidEditable(type);
1967
            }
1968

    
1969
            return avoidEditable(defaultFeatureType);
1970

    
1971
        } catch (Exception e) {
1972
            throw new GetFeatureTypeException(e, getName());
1973
        }
1974
    }
1975

    
1976
    private FeatureType avoidEditable(FeatureType ft) {
1977
        if (ft instanceof EditableFeatureType) {
1978
            return ((EditableFeatureType) ft).getNotEditableCopy();
1979
        } else {
1980
            return ft;
1981
        }
1982
    }
1983

    
1984
    @Override
1985
    public FeatureType getFeatureType(String featureTypeId)
1986
        throws DataException {
1987
        if (featureTypeId == null) {
1988
            return this.getDefaultFeatureType();
1989
        }
1990
        try {
1991
            if (isEditing()) {
1992
                FeatureType auxFeatureType =
1993
                    featureTypeManager.getType(featureTypeId);
1994
                if (auxFeatureType != null) {
1995
                    return auxFeatureType;
1996
                }
1997
            }
1998
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1999
            if (type != null) {
2000
                return type;
2001
            }
2002
            Iterator iter = this.featureTypes.iterator();
2003
            while (iter.hasNext()) {
2004
                type = (FeatureType) iter.next();
2005
                if (type.getId().equals(featureTypeId)) {
2006
                    return type;
2007
                }
2008
            }
2009
            return null;
2010
        } catch (Exception e) {
2011
            throw new GetFeatureTypeException(e, getName());
2012
        }
2013
    }
2014

    
2015
    public FeatureType getProviderDefaultFeatureType() {
2016
        return defaultFeatureType;
2017
    }
2018

    
2019
    @Override
2020
    public List getFeatureTypes() throws DataException {
2021
        try {
2022
            List types;
2023
            if (isEditing()) {
2024
                types = new ArrayList();
2025
                Iterator it = featureTypes.iterator();
2026
                while (it.hasNext()) {
2027
                    FeatureType type = (FeatureType) it.next();
2028
                    FeatureType typeaux =
2029
                        featureTypeManager.getType(type.getId());
2030
                    if (typeaux != null) {
2031
                        types.add(typeaux);
2032
                    } else {
2033
                        types.add(type);
2034
                    }
2035
                }
2036
                it = featureTypeManager.newsIterator();
2037
                while (it.hasNext()) {
2038
                    FeatureType type = (FeatureType) it.next();
2039
                    types.add(type);
2040
                }
2041
            } else {
2042
                types = this.transforms.getFeatureTypes();
2043
                if (types == null) {
2044
                    types = featureTypes;
2045
                }
2046
            }
2047
            return Collections.unmodifiableList(types);
2048
        } catch (Exception e) {
2049
            throw new GetFeatureTypeException(e, getName());
2050
        }
2051
    }
2052

    
2053
    public List getProviderFeatureTypes() throws DataException {
2054
        return Collections.unmodifiableList(this.featureTypes);
2055
    }
2056

    
2057
    @Override
2058
    public Feature createFeature(FeatureProvider data) throws DataException {
2059
        DefaultFeature feature = new DefaultFeature(this, data);
2060
        return feature;
2061
    }
2062

    
2063
    public Feature createFeature(FeatureProvider data, FeatureType type)
2064
        throws DataException {
2065
        // FIXME: falta por implementar
2066
        // Comprobar si es un subtipo del feature de data
2067
        // y construir un feature usando el subtipo.
2068
        // Probablemente requiera generar una copia del data.
2069
        throw new NotYetImplemented();
2070
    }
2071

    
2072
    @Override
2073
    public EditableFeature createNewFeature(FeatureType type,
2074
        Feature defaultValues) throws DataException {
2075
        try {
2076
            FeatureProvider data = createNewFeatureProvider(type);
2077
            DefaultEditableFeature feature =
2078
                new DefaultEditableFeature(this, data);
2079
            feature.initializeValues(defaultValues);
2080
            data.setNew(true);
2081

    
2082
            return feature;
2083
        } catch (Exception e) {
2084
            throw new CreateFeatureException(e, getName());
2085
        }
2086
    }
2087

    
2088
    private FeatureProvider createNewFeatureProvider(FeatureType type)
2089
        throws DataException {
2090
        type = this.fixFeatureType((DefaultFeatureType) type);
2091
        FeatureProvider data = this.provider.createFeatureProvider(type);
2092
        data.setNew(true);
2093
        if (type.hasOID() && (data.getOID() == null)) {
2094
            data.setOID(this.provider.createNewOID());
2095
        } else {
2096
            data.setOID(this.getTemporalOID());
2097
        }
2098
        return data;
2099

    
2100
    }
2101

    
2102
    @Override
2103
    public EditableFeature createNewFeature(FeatureType type,
2104
        boolean defaultValues) throws DataException {
2105
        try {
2106
            FeatureProvider data = createNewFeatureProvider(type);
2107
            DefaultEditableFeature feature =
2108
                new DefaultEditableFeature(this, data);
2109
            if (defaultValues) {
2110
                feature.initializeValues();
2111
            }
2112
            return feature;
2113
        } catch (Exception e) {
2114
            throw new CreateFeatureException(e, getName());
2115
        }
2116
    }
2117

    
2118
    @Override
2119
    public EditableFeature createNewFeature(boolean defaultValues)
2120
        throws DataException {
2121
        return this.createNewFeature(this.getDefaultFeatureType(),
2122
            defaultValues);
2123
    }
2124

    
2125
    @Override
2126
    public EditableFeature createNewFeature() throws DataException {
2127
        return this.createNewFeature(this.getDefaultFeatureType(), true);
2128
    }
2129

    
2130
    @Override
2131
    public EditableFeature createNewFeature(Feature defaultValues) throws DataException {
2132
        FeatureType ft = this.getDefaultFeatureType();
2133
        EditableFeature f = this.createNewFeature(ft, false);
2134
                for( FeatureAttributeDescriptor desc : ft ) {
2135
                        try {
2136
                                f.set(desc.getName(), defaultValues.get(desc.getName()));
2137
                        } catch(Throwable th) {
2138
                                // Ignore
2139
                        }
2140
                }
2141
        return f;
2142
    }
2143

    
2144
    @Override
2145
    public EditableFeatureType createFeatureType() {
2146
        EditableFeatureType ftype = this.dataManager.createFeatureType();
2147
        return ftype;
2148
    }
2149

    
2150
    @Override
2151
    public EditableFeatureType createFeatureType(String id) {
2152
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
2153
        return ftype;
2154
    }
2155

    
2156
    //
2157
    // ====================================================================
2158
    // Index related methods
2159
    //
2160

    
2161
    @Override
2162
    public FeatureIndexes getIndexes() {
2163
        return this.indexes;
2164
    }
2165

    
2166
    @Override
2167
    public FeatureIndex createIndex(FeatureType featureType,
2168
        String attributeName, String indexName) throws DataException {
2169
        return createIndex(null, featureType, attributeName, indexName);
2170
    }
2171

    
2172
    @Override
2173
    public FeatureIndex createIndex(String indexTypeName,
2174
        FeatureType featureType, String attributeName, String indexName)
2175
        throws DataException {
2176

    
2177
        return createIndex(indexTypeName, featureType, attributeName,
2178
            indexName, false, null);
2179
    }
2180

    
2181
    @Override
2182
    public FeatureIndex createIndex(FeatureType featureType,
2183
        String attributeName, String indexName, Observer observer)
2184
        throws DataException {
2185
        return createIndex(null, featureType, attributeName, indexName,
2186
            observer);
2187
    }
2188

    
2189
    @Override
2190
    public FeatureIndex createIndex(String indexTypeName,
2191
        FeatureType featureType, String attributeName, String indexName,
2192
        final Observer observer) throws DataException {
2193

    
2194
        return createIndex(indexTypeName, featureType, attributeName,
2195
            indexName, true, observer);
2196
    }
2197

    
2198
    private FeatureIndex createIndex(String indexTypeName,
2199
        FeatureType featureType, String attributeName, String indexName,
2200
        boolean background, final Observer observer) throws DataException {
2201

    
2202
        checkNotInAppendMode();
2203
        FeatureIndexProviderServices index;
2204
        index = dataManager.createFeatureIndexProvider(indexTypeName, this,
2205
                featureType, indexName,
2206
                featureType.getAttributeDescriptor(attributeName));
2207

    
2208
        try {
2209
            index.fill(background, observer);
2210
        } catch (FeatureIndexException e) {
2211
            throw new InitializeException(index.getName(), e);
2212
        }
2213

    
2214
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
2215
        return index;
2216
    }
2217

    
2218
    //
2219
    // ====================================================================
2220
    // Transforms related methods
2221
    //
2222

    
2223
    @Override
2224
    public FeatureStoreTransforms getTransforms() {
2225
        return this.transforms;
2226
    }
2227

    
2228
    @Override
2229
    public FeatureQuery createFeatureQuery() {
2230
        return new DefaultFeatureQuery();
2231
    }
2232

    
2233
    @Override
2234
    public DataQuery createQuery() {
2235
        return createFeatureQuery();
2236
    }
2237

    
2238
    //
2239
    // ====================================================================
2240
    // UndoRedo related methods
2241
    //
2242

    
2243
    @Override
2244
    public boolean canRedo() {
2245
        return commands.canRedo();
2246
    }
2247

    
2248
    @Override
2249
    public boolean canUndo() {
2250
        return commands.canUndo();
2251
    }
2252

    
2253
    @Override
2254
    public void redo(int num) throws RedoException {
2255
        for (int i = 0; i < num; i++) {
2256
            redo();
2257
        }
2258
    }
2259

    
2260
    @Override
2261
    public void undo(int num) throws UndoException {
2262
        for (int i = 0; i < num; i++) {
2263
            undo();
2264
        }
2265
    }
2266

    
2267
    //
2268
    // ====================================================================
2269
    // Metadata related methods
2270
    //
2271

    
2272
    @Override
2273
    public Object getMetadataID() {
2274
        return this.provider.getSourceId();
2275
    }
2276

    
2277
    @Override
2278
    public void delegate(DynObject dynObject) {
2279
        this.metadata.delegate(dynObject);
2280
    }
2281

    
2282
    @Override
2283
    public DynClass getDynClass() {
2284
        return this.metadata.getDynClass();
2285
    }
2286

    
2287
    @Override
2288
        public Object getDynValue(String name) throws DynFieldNotFoundException {
2289
                if( this.transforms.hasDynValue(name) ) {
2290
                        return this.transforms.getDynValue(name);
2291
                }
2292
                if (this.metadata.hasDynValue(name)) {
2293
                        return this.metadata.getDynValue(name);
2294
                }
2295
                if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
2296
                        return this.provider.getProviderName();
2297
                } else if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
2298
                        return this.provider.getSourceId();
2299
                } else if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
2300
                        try {
2301
                                return this.getDefaultFeatureType();
2302
                        } catch (DataException e) {
2303
                                return null;
2304
                        }
2305
                }
2306
                return this.metadata.getDynValue(name);
2307
        }
2308

    
2309
    @Override
2310
    public boolean hasDynValue(String name) {
2311
                if( this.transforms.hasDynValue(name) ) {
2312
                        return true;
2313
                }
2314
        return this.metadata.hasDynValue(name);
2315
    }
2316

    
2317
    @Override
2318
    public boolean hasDynMethod(String name) {
2319
        return ((DynObject_v2)this.metadata).hasDynMethod(name);
2320
    }
2321

    
2322
    @Override
2323
    public void implement(DynClass dynClass) {
2324
        this.metadata.implement(dynClass);
2325
    }
2326

    
2327
    @Override
2328
    public Object invokeDynMethod(String name, Object[] args)
2329
        throws DynMethodException {
2330
        return this.metadata.invokeDynMethod(this, name, args);
2331
    }
2332

    
2333
    @Override
2334
    public Object invokeDynMethod(int code, Object[] args)
2335
        throws DynMethodException {
2336
        return this.metadata.invokeDynMethod(this, code, args);
2337
    }
2338

    
2339
    @Override
2340
    public void setDynValue(String name, Object value)
2341
        throws DynFieldNotFoundException {
2342
                if( this.transforms.hasDynValue(name) ) {
2343
                        this.transforms.setDynValue(name, value);
2344
                        return;
2345
                }
2346
        this.metadata.setDynValue(name, value);
2347

    
2348
    }
2349

    
2350
    /*
2351
     * (non-Javadoc)
2352
     *
2353
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
2354
     */
2355
    @Override
2356
    public Set getMetadataChildren() {
2357
        return this.metadataChildren;
2358
    }
2359

    
2360
    /*
2361
     * (non-Javadoc)
2362
     *
2363
     * @see org.gvsig.metadata.Metadata#getMetadataName()
2364
     */
2365
    @Override
2366
    public String getMetadataName() {
2367
        return this.provider.getProviderName();
2368
    }
2369

    
2370
    public FeatureTypeManager getFeatureTypeManager() {
2371
        return this.featureTypeManager;
2372
    }
2373

    
2374
    @Override
2375
    public long getFeatureCount() throws DataException {
2376
        if (featureCount == null) {
2377
            featureCount = this.provider.getFeatureCount();
2378
        }
2379
        if (this.isEditing()) {
2380
            if(this.isAppending()) {
2381
                try{
2382
                    throw new IllegalStateException();
2383
                } catch(IllegalStateException e) {
2384
                    LOG.info("Call DefaultFeatureStore.getFeatureCount editing in mode APPEND");
2385
                    e.printStackTrace();
2386
                }
2387
                return -1;
2388
            } else {
2389
                return featureCount
2390
                    + this.featureManager.getDeltaSize();
2391
            }
2392
        }
2393
        return featureCount;
2394
    }
2395

    
2396
    private Long getTemporalOID() {
2397
        return this.temporalOid++;
2398
    }
2399

    
2400
    @Override
2401
    public FeatureType getProviderFeatureType(String featureTypeId) {
2402
        if (featureTypeId == null) {
2403
            return this.defaultFeatureType;
2404
        }
2405
        FeatureType type;
2406
        Iterator iter = this.featureTypes.iterator();
2407
        while (iter.hasNext()) {
2408
            type = (FeatureType) iter.next();
2409
            if (type.getId().equals(featureTypeId)) {
2410
                return type;
2411
            }
2412
        }
2413
        return null;
2414
    }
2415

    
2416
    @Override
2417
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
2418
        return ((DefaultFeature) feature).getData();
2419
    }
2420

    
2421
    @Override
2422
    public DataStore getStore() {
2423
        return this;
2424
    }
2425

    
2426
    @Override
2427
    public FeatureStore getFeatureStore() {
2428
        return this;
2429
    }
2430

    
2431
    @Override
2432
    public void createCache(String name, DynObject parameters)
2433
        throws DataException {
2434
        cache = dataManager.createFeatureCacheProvider(name, parameters);
2435
        if (cache == null) {
2436
            throw new CreateException("FeaureCacheProvider", null);
2437
        }
2438
        cache.apply(this, provider);
2439
        provider = cache;
2440

    
2441
        featureCount = null;
2442
    }
2443

    
2444
    @Override
2445
    public FeatureCache getCache() {
2446
        return cache;
2447
    }
2448

    
2449
    @Override
2450
    public void clear() {
2451
        if (metadata != null) {
2452
            metadata.clear();
2453
        }
2454
    }
2455

    
2456
    @Override
2457
    public String getName() {
2458
        if( this.provider != null ) {
2459
            return this.provider.getName();
2460
        }
2461
        if( this.parameters instanceof HasAFile ) {
2462
            return FilenameUtils.getName(((HasAFile)this.parameters).getFile().getName());
2463
        }
2464
        return "unknow";
2465
    }
2466

    
2467
    @Override
2468
    public String getFullName() {
2469
        try {
2470
            if( this.provider!=null ) {
2471
                return this.provider.getFullName();
2472
            }
2473
            if( this.parameters instanceof HasAFile ) {
2474
                return (((HasAFile)this.parameters).getFile().getAbsolutePath());
2475
            }
2476
            return null;
2477
        } catch(Throwable th) {
2478
            return null;
2479
        }
2480
    }
2481

    
2482
    @Override
2483
    public String getProviderName() {
2484
        if( this.provider!=null ) {
2485
            return this.provider.getProviderName();
2486
        }
2487
        if( this.parameters != null ) {
2488
            return this.parameters.getDataStoreName();
2489
        }
2490
        return null;
2491

    
2492
    }
2493

    
2494
    @Override
2495
    public boolean isKnownEnvelope() {
2496
        return this.provider.isKnownEnvelope();
2497
    }
2498

    
2499
    @Override
2500
    public boolean hasRetrievedFeaturesLimit() {
2501
        return this.provider.hasRetrievedFeaturesLimit();
2502
    }
2503

    
2504
    @Override
2505
    public int getRetrievedFeaturesLimit() {
2506
        return this.provider.getRetrievedFeaturesLimit();
2507
    }
2508

    
2509
    @Override
2510
    public Interval getInterval() {
2511
        if( this.timeSupport!=null ) {
2512
            return this.timeSupport.getInterval();
2513
        }
2514
        return this.provider.getInterval();
2515
    }
2516

    
2517
    @Override
2518
    public Collection getTimes() {
2519
        if( this.timeSupport!=null ) {
2520
            return this.timeSupport.getTimes();
2521
        }
2522
        return this.provider.getTimes();
2523
    }
2524

    
2525
    @Override
2526
    public Collection getTimes(Interval interval) {
2527
        if( this.timeSupport!=null ) {
2528
            return this.timeSupport.getTimes(interval);
2529
        }
2530
        return this.provider.getTimes(interval);
2531
    }
2532

    
2533
    public void setTimeSupport(FeatureStoreTimeSupport timeSupport) {
2534
        FeatureAttributeDescriptor attr;
2535
        DefaultFeatureType ft;
2536
        try {
2537
            ft = (DefaultFeatureType) this.getDefaultFeatureType();
2538
        } catch (DataException ex) {
2539
            throw new RuntimeException("Can't add time support, can't get the default feature type.", ex);
2540
        }
2541
        attr = ft.getAttributeDescriptor(timeSupport.getAttributeName());
2542
        if( attr != null ) {
2543
            throw new RuntimeException("Can't add time support, attribute '"+timeSupport.getAttributeName()+"'already exists.");
2544
        }
2545
        attr = ft.getAttributeDescriptor(timeSupport.getRequiredFieldNames()[0]);
2546
        if( attr != null ) {
2547
            throw new RuntimeException("Can't add time support over attribute '"+timeSupport.getAttributeName()+"', this attribute don't exists.");
2548
        }
2549
        DefaultEditableFeatureAttributeDescriptor attr2 = new DefaultEditableFeatureAttributeDescriptor();
2550
        attr2.setDataType(timeSupport.getDataType());
2551
        attr2.setIsTime(true);
2552
        attr2.setFeatureAttributeEmulator(timeSupport);
2553
        ft.add(attr2);
2554

    
2555
        this.timeSupport = timeSupport;
2556
    }
2557

    
2558
    @Override
2559
    public Object clone() throws CloneNotSupportedException {
2560

    
2561
        DataStoreParameters dsp = getParameters();
2562

    
2563
        DefaultFeatureStore cloned_store = null;
2564

    
2565
        try {
2566
            cloned_store = (DefaultFeatureStore) DALLocator.getDataManager().
2567
                openStore(this.getProviderName(), dsp);
2568
            if (transforms != null) {
2569
                cloned_store.transforms = (DefaultFeatureStoreTransforms) transforms.clone();
2570
                cloned_store.transforms.setStoreForClone(cloned_store);
2571
            }
2572
        } catch (Exception e) {
2573
            throw new CloneException(e);
2574
        }
2575
        return cloned_store;
2576

    
2577
    }
2578

    
2579
    @Override
2580
    public Feature getFeature(DynObject dynobject) {
2581
        if (dynobject instanceof DynObjectFeatureFacade){
2582
            Feature f = ((DynObjectFeatureFacade)dynobject).getFeature();
2583
            return f;
2584
        }
2585
        return null;
2586
    }
2587

    
2588
    @Override
2589
    public Iterator iterator() {
2590
        try {
2591
            return this.getFeatureSet().fastIterator();
2592
        } catch (DataException ex) {
2593
            throw new RuntimeException(ex);
2594
        }
2595
    }
2596

    
2597
    @Override
2598
    public ExpressionBuilder createExpressionBuilder() {
2599
        if( this.provider instanceof FeatureStoreProvider_v2 ) {
2600
            return ((FeatureStoreProvider_v2)this.provider).createExpression();
2601
        }
2602
        return new SQLBuilderBase();
2603
    }
2604

    
2605
    @Override
2606
    public ExpressionBuilder createExpression() {
2607
        return createExpressionBuilder();
2608
    }
2609

    
2610
    public FeatureSet features() throws DataException {
2611
        // This is to avoid jython to create a property with this name
2612
        // to access method getFeatures.
2613
        return this.getFeatureSet();
2614
    }
2615

    
2616
    @Override
2617
    public DataStoreProviderFactory getProviderFactory() {
2618
        DataStoreProviderFactory factory = dataManager.getStoreProviderFactory(parameters.getDataStoreName());
2619
        return factory;
2620
    }
2621

    
2622
    @Override
2623
    public void useCache(String providerName, DynObject parameters) throws DataException {
2624
        throw new UnsupportedOperationException();
2625
    }
2626

    
2627
    @Override
2628
    public boolean isBroken() {
2629
        return this.state.isBroken();
2630
    }
2631

    
2632
    @Override
2633
    public Throwable getBreakingsCause() {
2634
            return this.state.getBreakingsCause();
2635
    }
2636

    
2637
    @Override
2638
    public SpatialIndex wrapSpatialIndex(SpatialIndex index) {
2639
//      FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) this.getProviderFactory();
2640
//      if( !factory.supportNumericOID() ) {
2641
//          return null;
2642
//      }
2643
      SpatialIndex wrappedIndex = new WrappedSpatialIndex(index, this);
2644
      return wrappedIndex;
2645
  }
2646
}