Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 35464

History | View | Annotate | Download (63.1 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 IVER T.I. S.A.   {{Task}}
26
 */
27

    
28
package org.gvsig.fmap.dal.feature.impl;
29

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

    
145
public final class DefaultFeatureStore extends AbstractDisposable implements
146
    DataStoreInitializer, FeatureStoreProviderServices, FeatureStore,
147
    Observer {
148

    
149
    final static private Logger logger =
150
        LoggerFactory.getLogger(DefaultFeatureStore.class);
151

    
152
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
153

    
154
    private DataStoreParameters parameters = null;
155
    private FeatureSelection selection;
156
    private FeatureLocks locks;
157

    
158
    private DelegateWeakReferencingObservable delegateObservable =
159
        new DelegateWeakReferencingObservable(this);
160

    
161
    private FeatureCommandsStack commands;
162
    private FeatureTypeManager featureTypeManager;
163
    private FeatureManager featureManager;
164
    private SpatialManager spatialManager;
165

    
166
    private FeatureType defaultFeatureType = null;
167
    private List featureTypes = new ArrayList();
168

    
169
    private int mode = MODE_QUERY;
170
    private long versionOfUpdate = 0;
171
    private boolean hasStrongChanges = true;
172
    private boolean hasInserts = true;
173

    
174
    private DefaultDataManager dataManager = null;
175

    
176
    private FeatureStoreProvider provider = null;
177

    
178
    private DefaultFeatureIndexes indexes;
179

    
180
    private DefaultFeatureStoreTransforms transforms;
181

    
182
    private DelegatedDynObject metadata;
183
    private Set metadataChildren;
184

    
185
    private Long featureCount = null;
186

    
187
    private long temporalOid = 0;
188

    
189
    private FeatureCacheProvider cache;
190

    
191
    /*
192
     * TODO:
193
     * 
194
     * - Comprobar que solo se pueden a�adir reglas de validacion sobre un
195
     * EditableFeatureType. - Comprobar que solo se puede hacer un update con un
196
     * featureType al que se le han cambiado las reglas de validacion cuando
197
     * hasStrongChanges=false.
198
     */
199

    
200
    public DefaultFeatureStore() {
201

    
202
    }
203

    
204
    public void intializePhase1(DataManager dataManager,
205
        DataStoreParameters parameters) throws InitializeException {
206

    
207
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
208

    
209
        this.metadata =
210
            (DelegatedDynObject) dynManager.createDynObject(
211
                METADATA_DEFINITION_NAME, MetadataManager.METADATA_NAMESPACE);
212

    
213
        this.dataManager = (DefaultDataManager)dataManager;
214

    
215
        this.parameters = parameters;
216
        this.transforms = new DefaultFeatureStoreTransforms(this);
217
        try {
218
            indexes = new DefaultFeatureIndexes(this);
219
        } catch (DataException e) {
220
            throw new InitializeException(e);
221
        }
222

    
223
    }
224

    
225
    public void intializePhase2(DataStoreProvider provider) {
226
        this.provider = (FeatureStoreProvider) provider;
227
        this.delegate(provider);
228
        this.metadataChildren = new HashSet();
229
        this.metadataChildren.add(provider);
230
    }
231

    
232
    public DataStoreParameters getParameters() {
233
        return parameters;
234
    }
235

    
236
    public int getMode() {
237
        return this.mode;
238
    }
239

    
240
    public DataManager getManager() {
241
        return this.dataManager;
242
    }
243

    
244
    public Iterator getChildren() {
245
        return this.provider.getChilds();
246
    }
247

    
248
    public FeatureStoreProvider getProvider() {
249
        return this.provider;
250
    }
251

    
252
    public FeatureManager getFeatureManager() {
253
        return this.featureManager;
254
    }
255

    
256
    public void setFeatureTypes(List types, FeatureType defaultType) {
257
        this.featureTypes = types;
258
        this.defaultFeatureType = defaultType;
259
    }
260

    
261
    public void open() throws OpenException {
262
        // TODO: Se puede hacer un open estando en edicion ?
263
        this.notifyChange(DataStoreNotification.BEFORE_OPEN);
264
        this.provider.open();
265
        this.notifyChange(DataStoreNotification.AFTER_OPEN);
266
    }
267

    
268
    public void refresh() throws OpenException, InitializeException {
269
        if (this.mode != MODE_QUERY) {
270
            throw new IllegalStateException();
271
        }
272
        this.notifyChange(FeatureStoreNotification.BEFORE_REFRESH);
273
        this.featureCount = null;
274
        this.provider.refresh();
275
        this.notifyChange(FeatureStoreNotification.AFTER_REFRESH);
276
    }
277

    
278
    public void close() throws CloseException {
279
        // TODO: Se puede hacer un close estando en edicion ?
280
        this.notifyChange(DataStoreNotification.BEFORE_CLOSE);
281
        this.featureCount = null;
282
        this.provider.close();
283
        this.notifyChange(DataStoreNotification.AFTER_CLOSE);
284
    }
285

    
286
    protected void doDispose() throws BaseException {
287
        this.notifyChange(DataStoreNotification.BEFORE_DISPOSE);
288
        this.provider.dispose();
289
        if (this.selection != null) {
290
            this.selection.dispose();
291
            this.selection = null;
292
        }
293
        this.commands = null;
294
        this.featureCount = null;
295
        if (this.locks != null) {
296
            // this.locks.dispose();
297
            this.locks = null;
298
        }
299

    
300
        if (this.featureTypeManager != null) {
301
            this.featureTypeManager.dispose();
302
            this.featureTypeManager = null;
303
        }
304

    
305
        this.featureManager = null;
306
        this.spatialManager = null;
307

    
308
        this.parameters = null;
309
        this.notifyChange(DataStoreNotification.AFTER_DISPOSE);
310
        if (delegateObservable != null) {
311
            this.delegateObservable.deleteObservers();
312
            this.delegateObservable = null;
313
        }
314
    }
315

    
316
    public boolean allowWrite() {
317
        return this.provider.allowWrite();
318
    }
319

    
320
    public boolean canWriteGeometry(int geometryType) throws DataException {
321
        return this.provider.canWriteGeometry(geometryType, 0);
322
    }
323

    
324
    public DataServerExplorer getExplorer() throws ReadException,
325
        ValidateDataParametersException {
326
        return this.provider.getExplorer();
327
    }
328

    
329
    /*
330
     * public Metadata getMetadata() throws MetadataNotFoundException {
331
     * // TODO:
332
     * // Si el provider devuelbe null habria que ver de construir aqui
333
     * // los metadatos basicos, como el Envelope y el SRS.
334
     * 
335
     * // TODO: Estando en edicion el Envelope deberia de
336
     * // actualizarse usando el spatialManager
337
     * return this.provider.getMetadata();
338
     * }
339
     */
340

    
341
    public Envelope getEnvelope() throws DataException {
342
        if (this.mode == MODE_FULLEDIT) {
343
            return this.spatialManager.getEnvelope();
344
        }
345
        return this.provider.getEnvelope();
346
    }
347

    
348
    /**
349
     * @deprecated use getDefaultFeatureType().getDefaultSRS()
350
     */
351
    public IProjection getSRSDefaultGeometry() throws DataException {
352
        return this.getDefaultFeatureType().getDefaultSRS();
353
    }
354

    
355
    public FeatureSelection createDefaultFeatureSelection()
356
        throws DataException {
357
        return new DefaultFeatureSelection(this);
358
    }
359

    
360
    public FeatureProvider createDefaultFeatureProvider(FeatureType type)
361
        throws DataException {
362
        if (type.hasOID()) {
363
            return new DefaultFeatureProvider(type, this.provider
364
                .createNewOID());
365
        }
366
        return new DefaultFeatureProvider(type);
367
    }
368

    
369
    public void saveToState(PersistentState state) throws PersistenceException {
370
        if (this.mode != FeatureStore.MODE_QUERY) {
371
            throw new PersistenceException(new IllegalStateException(this
372
                .getName()));
373
        }
374
        state.set("dataStoreName", this.getName());
375
        state.set("parameters", this.parameters);
376
        state.set("selection", this.selection);
377
        state.set("transforms", this.transforms);
378
        // TODO locks persistence
379
        // state.set("locks", this.locks);
380
        // TODO indexes persistence
381
        // state.set("indexes", this.indexes);
382
        Map evaluatedAttr = new HashMap(1);
383
        Iterator iterType = featureTypes.iterator();
384
        Iterator iterAttr;
385
        FeatureType type;
386
        DefaultFeatureAttributeDescriptor attr;
387
        List attrs;
388
        while (iterType.hasNext()) {
389
            type = (FeatureType) iterType.next();
390
            attrs = new ArrayList();
391
            iterAttr = type.iterator();
392
            while (iterAttr.hasNext()) {
393
                attr = (DefaultFeatureAttributeDescriptor) iterAttr.next();
394
                if ((attr.getEvaluator() != null)
395
                    && (attr.getEvaluator() instanceof Persistent)) {
396
                    attrs.add(attr);
397
                }
398
            }
399
            if (!attrs.isEmpty()) {
400
                evaluatedAttr.put(type.getId(), attrs);
401
            }
402

    
403
        }
404

    
405
        if (evaluatedAttr.isEmpty()) {
406
            evaluatedAttr = null;
407
        }
408

    
409
        state.set("evaluatedAttributes", evaluatedAttr);
410
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
411

    
412
    }
413

    
414
    public void loadFromState(PersistentState state)
415
        throws PersistenceException {
416
        if (this.provider != null) {
417
            throw new PersistenceStoreAlreadyLoadedException(this.getName());
418
        }
419
        if (this.getManager() == null) {
420
            this.dataManager = (DefaultDataManager) DALLocator.getDataManager();
421
        }
422

    
423
        DataStoreParameters params =
424
            (DataStoreParameters) state.get("parameters");
425

    
426
        try {
427

    
428
            this.dataManager.intializeDataStore(this, params);
429
            this.selection = (FeatureSelection) state.get("selection");
430
            this.transforms =
431
                (DefaultFeatureStoreTransforms) state.get("transforms");
432
            Map evaluatedAttributes = (Map) state.get("evaluatedAttributes");
433
            if ((evaluatedAttributes != null) && !evaluatedAttributes.isEmpty()) {
434
                List attrs;
435
                Iterator iterEntries =
436
                    evaluatedAttributes.entrySet().iterator();
437
                Entry entry;
438
                while (iterEntries.hasNext()) {
439
                    entry = (Entry) iterEntries.next();
440
                    attrs = (List) entry.getValue();
441
                    if (attrs.isEmpty()) {
442
                        continue;
443
                    }
444
                    int fTypePos = -1;
445
                    DefaultFeatureType type = null;
446
                    for (int i = 0; i < featureTypes.size(); i++) {
447
                        type = (DefaultFeatureType) featureTypes.get(i);
448
                        if (type.getId().equals(entry.getKey())) {
449
                            fTypePos = i;
450
                            break;
451
                        }
452
                    }
453
                    if (fTypePos < 0) {
454
                        throw new PersistenceCantFindFeatureTypeException(this
455
                            .getName(), (String) entry.getKey());
456
                    }
457
                    DefaultEditableFeatureType eType =
458
                        (DefaultEditableFeatureType) type.getEditable();
459
                    Iterator iterAttr = attrs.iterator();
460
                    FeatureAttributeDescriptor attr;
461
                    while (iterAttr.hasNext()) {
462
                        attr = (FeatureAttributeDescriptor) iterAttr.next();
463
                        eType.addLike(attr);
464
                    }
465
                    featureTypes.set(fTypePos, eType.getNotEditableCopy());
466

    
467
                }
468

    
469
            }
470

    
471
            String defFTypeid = state.getString("defaultFeatureTypeId");
472
            FeatureType ftype = null;
473
            if (!this.defaultFeatureType.getId().equals(
474
                state.getString("defaultFeatureTypeId"))) {
475

    
476
                ftype = getFeatureType(defFTypeid);
477
                if (ftype == null) {
478
                    throw new PersistenceCantFindDefaultFeatureTypeException(
479
                        this.getName(), defFTypeid);
480
                }
481
                this.defaultFeatureType = ftype;
482
            }
483

    
484
        } catch (InitializeException e) {
485
            throw new PersistenceException(e);
486
        } catch (DataException e) {
487
            throw new PersistenceException(e);
488
        }
489

    
490
    }
491

    
492
    public static void registerPersistenceDefinition() {
493
        PersistenceManager manager = ToolsLocator.getPersistenceManager();
494
        if (manager.getDefinition(PERSISTENCE_DEFINITION_NAME) == null) {
495
            DynStruct definition =
496
                manager.addDefinition(DefaultFeatureStore.class,
497
                    PERSISTENCE_DEFINITION_NAME, PERSISTENCE_DEFINITION_NAME
498
                        + " Persistent definition", null, null);
499
            definition.addDynFieldString("dataStoreName").setMandatory(true)
500
                .setPersistent(true);
501

    
502
            definition.addDynFieldObject("parameters").setClassOfValue(
503
                DynObject.class).setMandatory(true).setPersistent(true);
504

    
505
            definition.addDynFieldObject("selection").setClassOfValue(
506
                FeatureSelection.class).setMandatory(false).setPersistent(true);
507

    
508
            definition.addDynFieldObject("transforms").setClassOfValue(
509
                DefaultFeatureStoreTransforms.class).setMandatory(true)
510
                .setPersistent(true);
511

    
512
            definition.addDynFieldMap("evaluatedAttributes").setClassOfItems(
513
                List.class) // List<DefaultFeatureAttributeDescriptor>
514
                .setMandatory(false).setPersistent(true);
515

    
516
            definition.addDynFieldString("defaultFeatureTypeId").setMandatory(
517
                true).setPersistent(true);
518
        }
519
    }
520

    
521
    public static void registerMetadataDefinition() throws MetadataException {
522
        MetadataManager manager = MetadataLocator.getMetadataManager();
523
        if (manager.getDefinition(METADATA_DEFINITION_NAME) == null) {
524
            DynStruct metadataDefinition =
525
                manager.addDefinition(METADATA_DEFINITION_NAME, null);
526
            metadataDefinition.extend(manager
527
                .getDefinition(DataStore.METADATA_DEFINITION_NAME));
528
        }
529
    }
530

    
531
    //
532
    // ====================================================================
533
    // Gestion de la seleccion
534
    //
535

    
536
    public void setSelection(DataSet selection) throws DataException {
537
        this.setSelection((FeatureSet) selection);
538
    }
539

    
540
    public DataSet createSelection() throws DataException {
541
        return createFeatureSelection();
542
    }
543

    
544
    public DataSet getSelection() throws DataException {
545
        return this.getFeatureSelection();
546
    }
547

    
548
    public void setSelection(FeatureSet selection) throws DataException {
549
        setSelection(selection, true);
550
    }
551

    
552
    /**
553
     * @see #setSelection(FeatureSet)
554
     * @param undoable
555
     *            if the action must be undoable
556
     */
557
    public void setSelection(FeatureSet selection, boolean undoable)
558
        throws DataException {
559
        if (selection == null) {
560
            if (undoable) {
561
                throw new SelectionNotAllowedException(getName());
562
            }
563

    
564
        } else {
565
            if (selection.equals(this.selection)) {
566
                return;
567
            }
568
            if (!selection.isFromStore(this)) {
569
                throw new SelectionNotAllowedException(getName());
570
            }
571
        }
572

    
573
        if (this.selection != null) {
574
            this.selection.deleteObserver(this);
575
        }
576
        if (selection == null) {
577
            if (this.selection != null) {
578
                this.selection.dispose();
579
            }
580
            this.selection = null;
581
            return;
582
        }
583
        if (selection instanceof FeatureSelection) {
584
            if (undoable && isEditing()) {
585
                commands.selectionSet(this, this.selection,
586
                    (FeatureSelection) selection);
587
            }
588
            if (this.selection != null) {
589
                this.selection.dispose();
590
            }
591
            this.selection = (FeatureSelection) selection;
592
        } else {
593
            if (undoable && isEditing()) {
594
                commands.startComplex("_selectionSet");
595
            }
596
            if (selection instanceof DefaultFeatureSelection) {
597
                DefaultFeatureSelection defSelection =
598
                    (DefaultFeatureSelection) selection;
599
                defSelection.deselectAll(undoable);
600
                defSelection.select(selection, undoable);
601
            } else {
602
                this.selection.deselectAll();
603
                this.selection.select(selection);
604
            }
605
            if (undoable && isEditing()) {
606
                commands.endComplex();
607
            }
608
        }
609
        this.selection.addObserver(this);
610

    
611
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
612
    }
613

    
614
    public FeatureSelection createFeatureSelection() throws DataException {
615
        return this.provider.createFeatureSelection();
616
    }
617

    
618
    public FeatureSelection getFeatureSelection() throws DataException {
619
        if (selection == null) {
620
            this.selection = createFeatureSelection();
621
            this.selection.addObserver(this);
622
        }
623
        return selection;
624
    }
625

    
626
    //
627
    // ====================================================================
628
    // Gestion de notificaciones
629
    //
630

    
631
    public void notifyChange(String notification) {
632
        if (delegateObservable != null) {
633
            notifyChange(new DefaultFeatureStoreNotification(this, notification));
634
        }
635

    
636
    }
637

    
638
    public void notifyChange(String notification, FeatureProvider data) {
639
        try {
640
            notifyChange(notification, createFeature(data));
641
        } catch (DataException ex) {
642
            logger.error("Error notifying about the notification: "
643
                + notification + ", with the data: " + data, ex);
644
        }
645
    }
646

    
647
    public void notifyChange(String notification, Feature feature) {
648
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
649
            feature));
650
    }
651

    
652
    public void notifyChange(String notification, Command command) {
653
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
654
            command));
655
    }
656

    
657
    public void notifyChange(String notification, EditableFeatureType type) {
658
        notifyChange(new DefaultFeatureStoreNotification(this, notification,
659
            type));
660
    }
661

    
662
    public void notifyChange(FeatureStoreNotification storeNotification) {
663
        delegateObservable.notifyObservers(storeNotification);
664
    }
665

    
666
    public void notifyChange(String notification, Resource resource) {
667
        notifyChange(new DefaultFeatureStoreNotification(this,
668
            DataStoreNotification.RESOURCE_CHANGED));
669
    }
670

    
671
    //
672
    // ====================================================================
673
    // Gestion de bloqueos
674
    //
675

    
676
    public boolean isLocksSupported() {
677
        return this.provider.isLocksSupported();
678
    }
679

    
680
    public FeatureLocks getLocks() throws DataException {
681
        if (!this.provider.isLocksSupported()) {
682
            logger.warn("Locks not supporteds");
683
            return null;
684
        }
685
        if (locks == null) {
686
            this.locks = this.provider.createFeatureLocks();
687
        }
688
        return locks;
689
    }
690

    
691
    //
692
    // ====================================================================
693
    // Interface Observable
694
    //
695

    
696
    public void disableNotifications() {
697
        this.delegateObservable.disableNotifications();
698

    
699
    }
700

    
701
    public void enableNotifications() {
702
        this.delegateObservable.enableNotifications();
703
    }
704

    
705
    public void beginComplexNotification() {
706
        this.delegateObservable.beginComplexNotification();
707

    
708
    }
709

    
710
    public void endComplexNotification() {
711
        this.delegateObservable.endComplexNotification();
712

    
713
    }
714

    
715
    public void addObserver(Observer observer) {
716
        this.delegateObservable.addObserver(observer);
717

    
718
    }
719

    
720
    public void deleteObserver(Observer observer) {
721
        if (delegateObservable != null) {
722
            this.delegateObservable.deleteObserver(observer);
723
        }
724
    }
725

    
726
    public void deleteObservers() {
727
        this.delegateObservable.deleteObservers();
728

    
729
    }
730

    
731
    //
732
    // ====================================================================
733
    // Interface Observer
734
    //
735
    // Usado para observar:
736
    // - su seleccion
737
    // - sus bloqueos
738
    // - sus recursos
739
    //
740

    
741
    public void update(Observable observable, Object notification) {
742
        if (observable instanceof FeatureSet) {
743
            if (observable == this.selection) {
744
                this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
745
            } else
746
                if (observable == this.locks) {
747
                    this.notifyChange(FeatureStoreNotification.LOCKS_CHANGE);
748
                }
749

    
750
        } else
751
            if (observable instanceof FeatureStoreProvider) {
752
                if (observable == this.provider) {
753

    
754
                }
755

    
756
            }
757
    }
758

    
759
    //
760
    // ====================================================================
761
    // Edicion
762
    //
763

    
764
    private void newVersionOfUpdate() {
765
        this.versionOfUpdate++;
766
    }
767

    
768
    private long currentVersionOfUpdate() {
769
        return this.versionOfUpdate;
770
    }
771

    
772
    private void checkInEditingMode() throws NeedEditingModeException {
773
        if (mode != MODE_FULLEDIT) {
774
            throw new NeedEditingModeException(this.getName());
775
        }
776
    }
777

    
778
    private void checkNotInAppendMode() throws IllegalStateException {
779
        if (mode == MODE_APPEND) {
780
            throw new IllegalStateException(this.getName());
781
        }
782
    }
783

    
784
    private void checkIsOwnFeature(Feature feature)
785
        throws IllegalFeatureException {
786
        if (((DefaultFeature) feature).getStore() != this) {
787
            throw new IllegalFeatureException(this.getName());
788
        }
789
        // FIXME: fixFeatureType no vale para el checkIsOwnFeature
790
        // fixFeatureType((DefaultFeatureType) feature.getType());
791
    }
792

    
793
    private void exitEditingMode() {
794
        if (commands != null) {
795
            commands.clear();
796
            commands = null;
797
        }
798

    
799
        if (featureTypeManager != null) {
800
            featureTypeManager.dispose();
801
            featureTypeManager = null;
802

    
803
        }
804

    
805
        // TODO implementar un dispose para estos dos
806
        featureManager = null;
807
        spatialManager = null;
808

    
809
        featureCount = null;
810

    
811
        mode = MODE_QUERY;
812
        hasStrongChanges = true; // Lo deja a true por si las moscas
813
        hasInserts = true;
814
    }
815

    
816
    synchronized public void edit() throws DataException {
817
        edit(MODE_FULLEDIT);
818
    }
819

    
820
    synchronized public void edit(int mode) throws DataException {
821
        try {
822
            if (this.mode != MODE_QUERY) {
823
                throw new AlreadyEditingException(this.getName());
824
            }
825
            if (!this.provider.supportsAppendMode()) {
826
                mode = MODE_FULLEDIT;
827
            }
828
            switch (mode) {
829
            case MODE_QUERY:
830
                throw new IllegalStateException(this.getName());
831

    
832
            case MODE_FULLEDIT:
833
                if (!this.transforms.isEmpty()) {
834
                    throw new IllegalStateException(this.getName());
835
                }
836
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
837
                featureManager =
838
                    new FeatureManager(new MemoryExpansionAdapter());
839
                featureTypeManager =
840
                    new FeatureTypeManager(this, new MemoryExpansionAdapter());
841
                spatialManager =
842
                    new SpatialManager(this, provider.getEnvelope());
843

    
844
                commands =
845
                    new DefaultFeatureCommandsStack(featureManager,
846
                        spatialManager, featureTypeManager);
847
                this.mode = MODE_FULLEDIT;
848
                hasStrongChanges = false;
849
                hasInserts = false;
850
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
851
                break;
852
            case MODE_APPEND:
853
                if (!this.transforms.isEmpty()) {
854
                    throw new IllegalStateException(this.getName());
855
                }
856
                notifyChange(FeatureStoreNotification.BEFORE_STARTEDITING);
857
                this.provider.beginAppend();
858
                this.mode = MODE_APPEND;
859
                hasInserts = false;
860
                notifyChange(FeatureStoreNotification.AFTER_STARTEDITING);
861
                break;
862
            }
863
        } catch (Exception e) {
864
            throw new StoreEditException(e, this.getName());
865
        }
866
    }
867

    
868
    public boolean isEditing() {
869
        return mode == MODE_FULLEDIT;
870
    }
871

    
872
    public boolean isAppending() {
873
        return mode == MODE_APPEND;
874
    }
875

    
876
    synchronized public void update(EditableFeatureType type)
877
        throws DataException {
878
        try {
879
            checkInEditingMode();
880
            if (type == null) {
881
                throw new NullFeatureTypeException(getName());
882
            }
883
            // FIXME: Comprobar que es un featureType aceptable.
884
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE_TYPE, type);
885
            newVersionOfUpdate();
886

    
887
            FeatureType oldt = type.getSource().getCopy();
888
            FeatureType newt = type.getNotEditableCopy();
889
            commands.update(newt, oldt);
890

    
891
            if (((DefaultEditableFeatureType) type).hasStrongChanges()) {
892
                hasStrongChanges = true;
893
            }
894
            notifyChange(FeatureStoreNotification.AFTER_UPDATE_TYPE, type);
895
        } catch (Exception e) {
896
            throw new StoreUpdateFeatureTypeException(e, this.getName());
897
        }
898
    }
899

    
900
    synchronized public void delete(Feature feature) throws DataException {
901
        try {
902
            checkInEditingMode();
903
            checkIsOwnFeature(feature);
904
            if (feature instanceof EditableFeature) {
905
                throw new StoreDeleteEditableFeatureException(getName());
906
            }
907
            notifyChange(FeatureStoreNotification.BEFORE_DELETE, feature);
908
            this.commands.delete(feature);
909
            newVersionOfUpdate();
910
            hasStrongChanges = true;
911
            notifyChange(FeatureStoreNotification.AFTER_DELETE, feature);
912
        } catch (Exception e) {
913
            throw new StoreDeleteFeatureException(e, this.getName());
914
        }
915
    }
916

    
917
    private static EditableFeature lastChangedFeature = null;
918

    
919
    synchronized public void insert(EditableFeature feature)
920
        throws DataException {
921
        try {
922
            switch (mode) {
923
            case MODE_QUERY:
924
                throw new NeedEditingModeException(this.getName());
925

    
926
            case MODE_APPEND:
927
                checkIsOwnFeature(feature);
928
                if (feature.getSource() != null) {
929
                    throw new NoNewFeatureInsertException(this.getName());
930
                }
931
                this.featureCount = null;
932
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
933
                feature.validate(Feature.UPDATE);
934
                provider.append(((DefaultEditableFeature) feature).getData());
935
                hasStrongChanges = true;
936
                hasInserts = true;
937
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
938
                break;
939

    
940
            case MODE_FULLEDIT:
941
                checkIsOwnFeature(feature);
942
                if (feature.getSource() != null) {
943
                    throw new NoNewFeatureInsertException(this.getName());
944
                }
945
                notifyChange(FeatureStoreNotification.BEFORE_INSERT, feature);
946
                newVersionOfUpdate();
947
                if ((lastChangedFeature == null)
948
                    || (lastChangedFeature.getSource() != feature.getSource())) {
949
                    lastChangedFeature = feature;
950
                    feature.validate(Feature.UPDATE);
951
                    lastChangedFeature = null;
952
                }
953
                commands.insert(feature.getNotEditableCopy());
954
                hasStrongChanges = true;
955
                hasInserts = true;
956
                notifyChange(FeatureStoreNotification.AFTER_INSERT, feature);
957
                break;
958
            }
959
        } catch (Exception e) {
960
            throw new StoreInsertFeatureException(e, this.getName());
961
        }
962
    }
963

    
964
    synchronized public void update(EditableFeature feature)
965
        throws DataException {
966
        try {
967
            if ((feature).getSource() == null) {
968
                insert(feature);
969
                return;
970
            }
971
            checkInEditingMode();
972
            checkIsOwnFeature(feature);
973
            notifyChange(FeatureStoreNotification.BEFORE_UPDATE, feature);
974
            newVersionOfUpdate();
975
            if ((lastChangedFeature == null)
976
                || (lastChangedFeature.getSource() != feature.getSource())) {
977
                lastChangedFeature = feature;
978
                feature.validate(Feature.UPDATE);
979
                lastChangedFeature = null;
980
            }
981

    
982
            Feature oldf = feature.getSource();
983
            Feature newf = feature.getNotEditableCopy();
984
            commands.update(newf, oldf);
985

    
986
            hasStrongChanges = true;
987
            notifyChange(FeatureStoreNotification.AFTER_UPDATE, feature);
988
        } catch (Exception e) {
989
            throw new StoreUpdateFeatureException(e, this.getName());
990
        }
991
    }
992

    
993
    synchronized public void redo() throws RedoException {
994
        Command redo = commands.getNextRedoCommand();
995
        try {
996
            checkInEditingMode();
997
        } catch (NeedEditingModeException ex) {
998
            throw new RedoException(redo, ex);
999
        }
1000
        notifyChange(FeatureStoreNotification.BEFORE_REDO, redo);
1001
        newVersionOfUpdate();
1002
        commands.redo();
1003
        hasStrongChanges = true;
1004
        notifyChange(FeatureStoreNotification.AFTER_REDO, redo);
1005
    }
1006

    
1007
    synchronized public void undo() throws UndoException {
1008
        Command undo = commands.getNextUndoCommand();
1009
        try {
1010
            checkInEditingMode();
1011
        } catch (NeedEditingModeException ex) {
1012
            throw new UndoException(undo, ex);
1013
        }
1014
        notifyChange(FeatureStoreNotification.BEFORE_UNDO, undo);
1015
        newVersionOfUpdate();
1016
        commands.undo();
1017
        hasStrongChanges = true;
1018
        notifyChange(FeatureStoreNotification.AFTER_UNDO, undo);
1019
    }
1020

    
1021
    public List getRedoInfos() {
1022
        if (isEditing() && (commands != null)) {
1023
            return commands.getRedoInfos();
1024
        } else {
1025
            return null;
1026
        }
1027
    }
1028

    
1029
    public List getUndoInfos() {
1030
        if (isEditing() && (commands != null)) {
1031
            return commands.getUndoInfos();
1032
        } else {
1033
            return null;
1034
        }
1035
    }
1036

    
1037
    public synchronized FeatureCommandsStack getCommandsStack()
1038
        throws DataException {
1039
        checkInEditingMode();
1040
        return commands;
1041
    }
1042

    
1043
    synchronized public void cancelEditing() throws DataException {
1044
        spatialManager.cancelModifies();
1045
        try {
1046
            checkInEditingMode();
1047

    
1048
            boolean clearSelection = this.hasStrongChanges;
1049
            if (this.selection instanceof FeatureReferenceSelection) {
1050
                clearSelection = this.hasInserts;
1051
            }
1052
            notifyChange(FeatureStoreNotification.BEFORE_CANCELEDITING);
1053
            exitEditingMode();
1054
            if (clearSelection) {
1055
                ((FeatureSelection) this.getSelection()).deselectAll();
1056
            }
1057
            notifyChange(FeatureStoreNotification.AFTER_CANCELEDITING);
1058
        } catch (Exception e) {
1059
            throw new StoreCancelEditingException(e, this.getName());
1060
        }
1061
    }
1062

    
1063
    synchronized public void finishEditing() throws DataException {
1064
        try {
1065
            switch (mode) {
1066
            case MODE_QUERY:
1067
                throw new NeedEditingModeException(this.getName());
1068

    
1069
            case MODE_APPEND:
1070
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1071
                provider.endAppend();
1072
                exitEditingMode();
1073
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1074
                break;
1075

    
1076
            case MODE_FULLEDIT:
1077
                if (hasStrongChanges && !this.allowWrite()) {
1078
                    throw new WriteNotAllowedException(getName());
1079
                }
1080

    
1081
                notifyChange(FeatureStoreNotification.BEFORE_FINISHEDITING);
1082
                if (hasStrongChanges) {
1083
                    validateFeatures(Feature.FINISH_EDITING);
1084
                    provider.performChanges(featureManager.getDeleted(),
1085
                        featureManager.getInserted(), featureManager
1086
                            .getUpdated(), featureTypeManager
1087
                            .getFeatureTypesChanged());
1088
                }
1089
                exitEditingMode();
1090
                notifyChange(FeatureStoreNotification.AFTER_FINISHEDITING);
1091
                break;
1092
            }
1093
        } catch (Exception e) {
1094
            throw new FinishEditingException(e);
1095
        }
1096
    }
1097

    
1098
    public void beginEditingGroup(String description)
1099
        throws NeedEditingModeException {
1100
        checkInEditingMode();
1101
        commands.startComplex(description);
1102
    }
1103

    
1104
    public void endEditingGroup() throws NeedEditingModeException {
1105
        checkInEditingMode();
1106
        commands.endComplex();
1107
    }
1108

    
1109
    public boolean isAppendModeSupported() {
1110
        return this.provider.supportsAppendMode();
1111
    }
1112

    
1113
    public void export(DataServerExplorer explorer, String provider,
1114
        NewFeatureStoreParameters params) throws DataException {
1115

    
1116
        if (this.getFeatureTypes().size() != 1) {
1117
            throw new NotYetImplemented(
1118
                "export whith more than one type not yet implemented");
1119
        }
1120
        FeatureSelection featureSelection = (FeatureSelection) getSelection();
1121
        FeatureStore target = null;
1122
        FeatureSet features = null;
1123
        DisposableIterator iterator = null;
1124
        try {
1125
            FeatureType type = this.getDefaultFeatureType();
1126
            if ((params.getDefaultFeatureType() == null)
1127
                || (params.getDefaultFeatureType().size() == 0)) {
1128
                params.setDefaultFeatureType(type.getEditable());
1129

    
1130
            }
1131
            explorer.add(provider, params, true);
1132

    
1133
            DataManager manager = DALLocator.getDataManager();
1134
            target = (FeatureStore) manager.openStore(provider, params);
1135
            FeatureType targetType = target.getDefaultFeatureType();
1136

    
1137
            target.edit(MODE_APPEND);
1138
            FeatureAttributeDescriptor[] pk = type.getPrimaryKey();
1139
            if (featureSelection.getSize() > 0) {
1140
                features = this.getFeatureSelection();
1141
            } else {
1142
                if ((pk != null) && (pk.length > 0)) {
1143
                    FeatureQuery query = createFeatureQuery();
1144
                    for (int i = 0; i < pk.length; i++) {
1145
                        query.getOrder().add(pk[i].getName(), true);
1146
                    }
1147
                    features = this.getFeatureSet(query);
1148
                } else {
1149
                    features = this.getFeatureSet();
1150
                }
1151
            }
1152
            iterator = features.iterator();
1153
            while (iterator.hasNext()) {
1154
                DefaultFeature feature = (DefaultFeature) iterator.next();
1155
                target.insert(target.createNewFeature(targetType, feature));
1156
            }
1157
            target.finishEditing();
1158
            target.dispose();
1159
        } catch (Exception e) {
1160
            throw new DataExportException(e, params.toString());
1161
        } finally {
1162
            dispose(iterator);
1163
            dispose(features);
1164
            dispose(target);
1165
        }
1166
    }
1167

    
1168
    //
1169
    // ====================================================================
1170
    // Obtencion de datos
1171
    // getDataCollection, getFeatureCollection
1172
    //
1173

    
1174
    public DataSet getDataSet() throws DataException {
1175
        checkNotInAppendMode();
1176
        FeatureQuery query =
1177
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1178
        return new DefaultFeatureSet(this, query);
1179
    }
1180

    
1181
    public DataSet getDataSet(DataQuery dataQuery) throws DataException {
1182
        checkNotInAppendMode();
1183
        return new DefaultFeatureSet(this, (FeatureQuery) dataQuery);
1184
    }
1185

    
1186
    public void getDataSet(Observer observer) throws DataException {
1187
        checkNotInAppendMode();
1188
        this.getFeatureSet(null, observer);
1189
    }
1190

    
1191
    public void getDataSet(DataQuery dataQuery, Observer observer)
1192
        throws DataException {
1193
        checkNotInAppendMode();
1194
        this.getFeatureSet((FeatureQuery) dataQuery, observer);
1195
    }
1196

    
1197
    public FeatureSet getFeatureSet() throws DataException {
1198
        checkNotInAppendMode();
1199
        FeatureQuery query =
1200
            new DefaultFeatureQuery(this.getDefaultFeatureType());
1201
        return new DefaultFeatureSet(this, query);
1202
    }
1203

    
1204
    public FeatureSet getFeatureSet(FeatureQuery featureQuery)
1205
        throws DataException {
1206
        checkNotInAppendMode();
1207
        return new DefaultFeatureSet(this, featureQuery);
1208
    }
1209

    
1210
    public void accept(Visitor visitor) throws BaseException {
1211
        FeatureSet set = getFeatureSet();
1212
        try {
1213
            set.accept(visitor);
1214
        } finally {
1215
            set.dispose();
1216
        }
1217
    }
1218

    
1219
    public void accept(Visitor visitor, DataQuery dataQuery)
1220
        throws BaseException {
1221
        FeatureSet set = getFeatureSet((FeatureQuery) dataQuery);
1222
        try {
1223
            set.accept(visitor);
1224
        } finally {
1225
            set.dispose();
1226
        }
1227
    }
1228

    
1229
    public FeatureType getFeatureType(FeatureQuery featureQuery)
1230
        throws DataException {
1231
        DefaultFeatureType fType =
1232
            (DefaultFeatureType) this.getFeatureType(featureQuery
1233
                .getFeatureTypeId());
1234
        if ((featureQuery.getAttributeNames() != null) && (featureQuery.getAttributeNames().length > 0)) {
1235
            return fType.getSubtype(featureQuery.getAttributeNames());
1236
        }
1237
        return fType;
1238
    }
1239

    
1240
    public void getFeatureSet(Observer observer) throws DataException {
1241
        checkNotInAppendMode();
1242
        this.getFeatureSet(null, observer);
1243
    }
1244

    
1245
    public void getFeatureSet(FeatureQuery query, Observer observer)
1246
        throws DataException {
1247
        class LoadInBackGround implements Runnable {
1248

    
1249
            private FeatureStore store;
1250
            private FeatureQuery query;
1251
            private Observer observer;
1252

    
1253
            public LoadInBackGround(FeatureStore store, FeatureQuery query,
1254
                Observer observer) {
1255
                this.store = store;
1256
                this.query = query;
1257
                this.observer = observer;
1258
            }
1259

    
1260
            void notify(FeatureStoreNotification theNotification) {
1261
                observer.update(store, theNotification);
1262
                return;
1263
            }
1264

    
1265
            public void run() {
1266
                FeatureSet set = null;
1267
                try {
1268
                    set = store.getFeatureSet(query);
1269
                    notify(new DefaultFeatureStoreNotification(store,
1270
                        FeatureStoreNotification.LOAD_FINISHED, set));
1271
                } catch (Exception e) {
1272
                    notify(new DefaultFeatureStoreNotification(store,
1273
                        FeatureStoreNotification.LOAD_FINISHED, e));
1274
                } finally {
1275
                    dispose(set);
1276
                }
1277
            }
1278
        }
1279

    
1280
        checkNotInAppendMode();
1281
        if (query == null) {
1282
            query = new DefaultFeatureQuery(this.getDefaultFeatureType());
1283
        }
1284
        LoadInBackGround task = new LoadInBackGround(this, query, observer);
1285
        Thread thread = new Thread(task);
1286
        thread.run();
1287
    }
1288

    
1289
    public Feature getFeatureByReference(FeatureReference reference)
1290
        throws DataException {
1291
        checkNotInAppendMode();
1292
        DefaultFeatureReference ref = (DefaultFeatureReference) reference;
1293
        FeatureType featureType;
1294
        if (ref.getFeatureTypeId() == null) {
1295
            featureType = this.getDefaultFeatureType();
1296
        } else {
1297
            featureType = this.getFeatureType(ref.getFeatureTypeId());
1298
        }
1299
        return this.getFeatureByReference(reference, featureType);
1300
    }
1301

    
1302
    public Feature getFeatureByReference(FeatureReference reference,
1303
        FeatureType featureType) throws DataException {
1304
        checkNotInAppendMode();
1305
        featureType = fixFeatureType((DefaultFeatureType) featureType);
1306
        if (!this.transforms.isEmpty()) {
1307

    
1308
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1309

    
1310
        }
1311
        // TODO comprobar que el id es de este store
1312

    
1313
        if (this.mode == MODE_FULLEDIT) {
1314
            Feature f = featureManager.get(reference, this, featureType);
1315
            if (f != null) {
1316
                return f;
1317
            }
1318
        }
1319
        DefaultFeature feature =
1320
            new DefaultFeature(this, this.provider
1321
                .getFeatureProviderByReference(
1322
                    (FeatureReferenceProviderServices) reference, featureType));
1323

    
1324
        if (!this.transforms.isEmpty()) {
1325
            return this.transforms.applyTransform(feature, featureType);
1326
        }
1327
        return feature;
1328
    }
1329

    
1330
    //
1331
    // ====================================================================
1332
    // Gestion de features
1333
    //
1334

    
1335
    private FeatureType fixFeatureType(DefaultFeatureType type)
1336
        throws DataException {
1337
        FeatureType original = this.getDefaultFeatureType();
1338

    
1339
        if ((type == null) || type.equals(original)) {
1340
            return original;
1341
        } else {
1342
            if (!type.isSubtypeOf(original)) {
1343
                Iterator iter = this.getFeatureTypes().iterator();
1344
                FeatureType tmpType;
1345
                boolean found = false;
1346
                while (iter.hasNext()) {
1347
                    tmpType = (FeatureType) iter.next();
1348
                    if (type.equals(tmpType)) {
1349
                        return type;
1350

    
1351
                    } else
1352
                        if (type.isSubtypeOf(tmpType)) {
1353
                            found = true;
1354
                            original = tmpType;
1355
                            break;
1356
                        }
1357

    
1358
                }
1359
                if (!found) {
1360
                    throw new IllegalFeatureTypeException(getName());
1361
                }
1362
            }
1363
        }
1364

    
1365
        // Checks that type has all fields of pk
1366
        // else add the missing attributes at the end.
1367
        if (!original.hasOID()) {
1368
            // Gets original pk attributes
1369
            DefaultEditableFeatureType edOriginal =
1370
                (DefaultEditableFeatureType) original.getEditable();
1371
            FeatureAttributeDescriptor orgAttr;
1372
            Iterator edOriginalIter = edOriginal.iterator();
1373
            while (edOriginalIter.hasNext()) {
1374
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1375
                if (!orgAttr.isPrimaryKey()) {
1376
                    edOriginalIter.remove();
1377
                }
1378
            }
1379

    
1380
            // Checks if all pk attributes are in type
1381
            Iterator typeIterator;
1382
            edOriginalIter = edOriginal.iterator();
1383
            FeatureAttributeDescriptor attr;
1384
            while (edOriginalIter.hasNext()) {
1385
                orgAttr = (FeatureAttributeDescriptor) edOriginalIter.next();
1386
                typeIterator = type.iterator();
1387
                while (typeIterator.hasNext()) {
1388
                    attr = (FeatureAttributeDescriptor) typeIterator.next();
1389
                    if (attr.getName().equals(orgAttr.getName())) {
1390
                        edOriginalIter.remove();
1391
                        break;
1392
                    }
1393
                }
1394
            }
1395

    
1396
            // add missing pk attributes if any
1397
            if (edOriginal.size() > 0) {
1398
                boolean isEditable = type instanceof DefaultEditableFeatureType;
1399
                DefaultEditableFeatureType edType =
1400
                    (DefaultEditableFeatureType) original.getEditable();
1401
                edType.clear();
1402
                edType.addAll(type);
1403
                edType.addAll(edOriginal);
1404
                if (!isEditable) {
1405
                    type = (DefaultFeatureType) edType.getNotEditableCopy();
1406
                }
1407
            }
1408

    
1409
        }
1410

    
1411
        return type;
1412
    }
1413

    
1414
    public void validateFeatures(int mode) throws DataException {
1415
        FeatureSet collection = null;
1416
        DisposableIterator iter = null;
1417
        try {
1418
            checkNotInAppendMode();
1419
            collection = this.getFeatureSet();
1420
            iter = collection.iterator();
1421
            long previousVersionOfUpdate = currentVersionOfUpdate();
1422
            while (iter.hasNext()) {
1423
                ((DefaultFeature) iter.next()).validate(mode);
1424
                if (previousVersionOfUpdate != currentVersionOfUpdate()) {
1425
                    throw new ConcurrentDataModificationException(getName());
1426
                }
1427
            }
1428
        } catch (Exception e) {
1429
            throw new ValidateFeaturesException(e, getName());
1430
        } finally {
1431
            dispose(iter);
1432
            dispose(collection);
1433
        }
1434
    }
1435

    
1436
    public FeatureType getDefaultFeatureType() throws DataException {
1437
        try {
1438
            if (isEditing()) {
1439
                FeatureType auxFeatureType =
1440
                    featureTypeManager.getType(defaultFeatureType.getId());
1441
                if (auxFeatureType != null) {
1442
                    return auxFeatureType;
1443
                }
1444
            }
1445
            FeatureType type = this.transforms.getDefaultFeatureType();
1446
            if (type != null) {
1447
                return type;
1448
            }
1449
            return defaultFeatureType;
1450
        } catch (Exception e) {
1451
            throw new GetFeatureTypeException(e, getName());
1452
        }
1453
    }
1454

    
1455
    public FeatureType getFeatureType(String featureTypeId)
1456
        throws DataException {
1457
        if (featureTypeId == null) {
1458
            return this.getDefaultFeatureType();
1459
        }
1460
        try {
1461
            if (isEditing()) {
1462
                FeatureType auxFeatureType =
1463
                    featureTypeManager.getType(featureTypeId);
1464
                if (auxFeatureType != null) {
1465
                    return auxFeatureType;
1466
                }
1467
            }
1468
            FeatureType type = this.transforms.getFeatureType(featureTypeId);
1469
            if (type != null) {
1470
                return type;
1471
            }
1472
            Iterator iter = this.featureTypes.iterator();
1473
            while (iter.hasNext()) {
1474
                type = (FeatureType) iter.next();
1475
                if (type.getId().equals(featureTypeId)) {
1476
                    return type;
1477
                }
1478
            }
1479
            return null;
1480
        } catch (Exception e) {
1481
            throw new GetFeatureTypeException(e, getName());
1482
        }
1483
    }
1484

    
1485
    public FeatureType getProviderDefaultFeatureType() {
1486
        return defaultFeatureType;
1487
    }
1488

    
1489
    public List getFeatureTypes() throws DataException {
1490
        try {
1491
            List types;
1492
            if (isEditing()) {
1493
                types = new ArrayList();
1494
                Iterator it = featureTypes.iterator();
1495
                while (it.hasNext()) {
1496
                    FeatureType type = (FeatureType) it.next();
1497
                    FeatureType typeaux =
1498
                        featureTypeManager.getType(type.getId());
1499
                    if (typeaux != null) {
1500
                        types.add(typeaux);
1501
                    } else {
1502
                        types.add(type);
1503
                    }
1504
                }
1505
                it = featureTypeManager.newsIterator();
1506
                while (it.hasNext()) {
1507
                    FeatureType type = (FeatureType) it.next();
1508
                    types.add(type);
1509
                }
1510
            } else {
1511
                types = this.transforms.getFeatureTypes();
1512
                if (types == null) {
1513
                    types = featureTypes;
1514
                }
1515
            }
1516
            return Collections.unmodifiableList(types);
1517
        } catch (Exception e) {
1518
            throw new GetFeatureTypeException(e, getName());
1519
        }
1520
    }
1521

    
1522
    public List getProviderFeatureTypes() throws DataException {
1523
        return Collections.unmodifiableList(this.featureTypes);
1524
    }
1525

    
1526
    public Feature createFeature(FeatureProvider data) throws DataException {
1527
        DefaultFeature feature = new DefaultFeature(this, data);
1528
        return feature;
1529
    }
1530

    
1531
    public Feature createFeature(FeatureProvider data, FeatureType type)
1532
        throws DataException {
1533
        // FIXME: falta por implementar
1534
        // Comprobar si es un subtipo del feature de data
1535
        // y construir un feature usando el subtipo.
1536
        // Probablemente requiera generar una copia del data.
1537
        throw new NotYetImplemented();
1538
    }
1539

    
1540
    public EditableFeature createNewFeature(FeatureType type,
1541
        Feature defaultValues) throws DataException {
1542
        try {
1543
            FeatureProvider data = createNewFeatureProvider(type);
1544
            DefaultEditableFeature feature =
1545
                new DefaultEditableFeature(this, data);
1546
            feature.initializeValues(defaultValues);
1547
            return feature;
1548
        } catch (Exception e) {
1549
            throw new CreateFeatureException(e, getName());
1550
        }
1551
    }
1552

    
1553
    private FeatureProvider createNewFeatureProvider(FeatureType type)
1554
        throws DataException {
1555
        type = this.fixFeatureType((DefaultFeatureType) type);
1556
        FeatureProvider data = this.provider.createFeatureProvider(type);
1557
        data.setNew(true);
1558
        if (type.hasOID() && (data.getOID() == null)) {
1559
            data.setOID(this.provider.createNewOID());
1560
        } else {
1561
            data.setOID(this.getTemporalOID());
1562
        }
1563
        return data;
1564

    
1565
    }
1566

    
1567
    public EditableFeature createNewFeature(FeatureType type,
1568
        boolean defaultValues) throws DataException {
1569
        try {
1570
            FeatureProvider data = createNewFeatureProvider(type);
1571
            DefaultEditableFeature feature =
1572
                new DefaultEditableFeature(this, data);
1573
            if (defaultValues) {
1574
                feature.initializeValues();
1575
            }
1576
            return feature;
1577
        } catch (Exception e) {
1578
            throw new CreateFeatureException(e, getName());
1579
        }
1580
    }
1581

    
1582
    public EditableFeature createNewFeature(boolean defaultValues)
1583
        throws DataException {
1584
        return this.createNewFeature(this.getDefaultFeatureType(),
1585
            defaultValues);
1586
    }
1587

    
1588
    public EditableFeature createNewFeature() throws DataException {
1589
        return this.createNewFeature(this.getDefaultFeatureType(), true);
1590
    }
1591

    
1592
    public EditableFeatureType createFeatureType() {
1593
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType();
1594
        return ftype;
1595
    }
1596

    
1597
    public EditableFeatureType createFeatureType(String id) {
1598
        DefaultEditableFeatureType ftype = new DefaultEditableFeatureType(id);
1599
        return ftype;
1600
    }
1601

    
1602
    //
1603
    // ====================================================================
1604
    // Index related methods
1605
    //
1606

    
1607
    public FeatureIndexes getIndexes() {
1608
        return this.indexes;
1609
    }
1610

    
1611
    public FeatureIndex createIndex(FeatureType featureType,
1612
        String attributeName, String indexName) throws DataException {
1613
        return createIndex(null, featureType, attributeName, indexName);
1614
    }
1615

    
1616
    public FeatureIndex createIndex(String indexTypeName,
1617
        FeatureType featureType, String attributeName, String indexName)
1618
        throws DataException {
1619
        checkNotInAppendMode();
1620
        FeatureIndexProviderServices index = null;
1621
        index =
1622
            dataManager.createFeatureIndexProvider(indexTypeName, this,
1623
                featureType, indexName, featureType
1624
                    .getAttributeDescriptor(attributeName));
1625
        try {
1626
            index.fill();
1627
        } catch (FeatureIndexException e) {
1628
            throw new InitializeException(index.getName(), e);
1629
        }
1630
        ((DefaultFeatureIndexes) getIndexes()).addIndex(index);
1631
        return index;
1632
    }
1633

    
1634
    public FeatureIndex createIndex(FeatureType featureType,
1635
        String attributeName, String indexName, Observer observer) {
1636
        return createIndex(null, featureType, attributeName, indexName,
1637
            observer);
1638
    }
1639

    
1640
    public FeatureIndex createIndex(String indexTypeName,
1641
        FeatureType featureType, String attributeName, String indexName,
1642
        Observer observer) {
1643
        // TODO Implement observer interaction
1644
        throw new UnsupportedOperationException();
1645
    }
1646

    
1647
    //
1648
    // ====================================================================
1649
    // Transforms related methods
1650
    //
1651

    
1652
    public FeatureStoreTransforms getTransforms() {
1653
        return this.transforms;
1654
    }
1655

    
1656
    public FeatureQuery createFeatureQuery() {
1657
        return new DefaultFeatureQuery();
1658
    }
1659

    
1660
    public DataQuery createQuery() {
1661
        return createFeatureQuery();
1662
    }
1663

    
1664
    //
1665
    // ====================================================================
1666
    // UndoRedo related methods
1667
    //
1668

    
1669
    public boolean canRedo() {
1670
        return commands.canRedo();
1671
    }
1672

    
1673
    public boolean canUndo() {
1674
        return commands.canUndo();
1675
    }
1676

    
1677
    public void redo(int num) throws RedoException {
1678
        commands.redo(num);
1679
    }
1680

    
1681
    public void undo(int num) throws UndoException {
1682
        commands.undo(num);
1683
    }
1684

    
1685
    //
1686
    // ====================================================================
1687
    // Metadata related methods
1688
    //
1689

    
1690
    public Object getMetadataID() {
1691
        return this.provider.getSourceId();
1692
    }
1693

    
1694
    public void delegate(DynObject dynObject) {
1695
        this.metadata.delegate(dynObject);
1696
    }
1697

    
1698
    public DynClass getDynClass() {
1699
        return this.metadata.getDynClass();
1700
    }
1701

    
1702
    public Object getDynValue(String name) throws DynFieldNotFoundException {
1703
        if (this.metadata.hasDynValue(name)) {
1704
            return this.metadata.getDynValue(name);
1705
        }
1706
        if (METADATA_PROVIDER.equalsIgnoreCase(name)) {
1707
            return this.provider.getProviderName();
1708
        } else
1709
            if (METADATA_CONTAINERNAME.equalsIgnoreCase(name)) {
1710
                return this.provider.getSourceId();
1711
            } else
1712
                if (METADATA_FEATURETYPE.equalsIgnoreCase(name)) {
1713
                    try {
1714
                        return this.getDefaultFeatureType();
1715
                    } catch (DataException e) {
1716
                        return null;
1717
                    }
1718
                }
1719
        return this.metadata.getDynValue(name);
1720
    }
1721

    
1722
    public boolean hasDynValue(String name) {
1723
        return this.metadata.hasDynValue(name);
1724
    }
1725

    
1726
    public void implement(DynClass dynClass) {
1727
        this.metadata.implement(dynClass);
1728
    }
1729

    
1730
    public Object invokeDynMethod(String name, DynObject context)
1731
        throws DynMethodException {
1732
        return this.metadata.invokeDynMethod(this, name, context);
1733
    }
1734

    
1735
    public Object invokeDynMethod(int code, DynObject context)
1736
        throws DynMethodException {
1737
        return this.metadata.invokeDynMethod(this, code, context);
1738
    }
1739

    
1740
    public void setDynValue(String name, Object value)
1741
        throws DynFieldNotFoundException {
1742
        this.metadata.setDynValue(name, value);
1743

    
1744
    }
1745

    
1746
    /*
1747
     * (non-Javadoc)
1748
     * 
1749
     * @see org.gvsig.metadata.Metadata#getMetadataChildren()
1750
     */
1751
    public Set getMetadataChildren() {
1752
        return this.metadataChildren;
1753
    }
1754

    
1755
    /*
1756
     * (non-Javadoc)
1757
     * 
1758
     * @see org.gvsig.metadata.Metadata#getMetadataName()
1759
     */
1760
    public String getMetadataName() {
1761
        return this.provider.getProviderName();
1762
    }
1763

    
1764
    public FeatureTypeManager getFeatureTypeManager() {
1765
        return this.featureTypeManager;
1766
    }
1767

    
1768
    public long getFeatureCount() throws DataException {
1769
        if (featureCount == null) {
1770
            featureCount = new Long(this.provider.getFeatureCount());
1771
        }
1772
        if (this.isEditing() && !this.isAppending()) {
1773
            return featureCount.longValue()
1774
                - this.featureManager.getDeltaSize();
1775
        }
1776
        return featureCount.longValue();
1777
    }
1778

    
1779
    private Long getTemporalOID() {
1780
        return new Long(this.temporalOid++);
1781
    }
1782

    
1783
    public FeatureType getProviderFeatureType(String featureTypeId) {
1784
        if (featureTypeId == null) {
1785
            return this.defaultFeatureType;
1786
        }
1787
        FeatureType type;
1788
        Iterator iter = this.featureTypes.iterator();
1789
        while (iter.hasNext()) {
1790
            type = (FeatureType) iter.next();
1791
            if (type.getId().equals(featureTypeId)) {
1792
                return type;
1793
            }
1794
        }
1795
        return null;
1796
    }
1797

    
1798
    public FeatureProvider getFeatureProviderFromFeature(Feature feature) {
1799
        return ((DefaultFeature) feature).getData();
1800
    }
1801

    
1802
    public DataStore getStore() {
1803
        return this;
1804
    }
1805

    
1806
    public FeatureStore getFeatureStore() {
1807
        return this;
1808
    }
1809

    
1810
    public void createCache(String name, DynObject parameters)
1811
        throws DataException {
1812
        cache = dataManager.createFeatureCacheProvider(name, parameters);
1813
        if (cache == null) {
1814
            throw new CreateException("FeaureCacheProvider", null);
1815
        }
1816
        cache.apply(this, provider);
1817
        provider = cache;
1818

    
1819
        featureCount = null;
1820
    }
1821

    
1822
    public FeatureCache getCache() {
1823
        return cache;
1824
    }
1825

    
1826
    public void clear() {
1827
        if (metadata != null) {
1828
            metadata.clear();
1829
        }
1830
    }
1831

    
1832
    public String getName() {
1833
        return this.provider.getName();
1834
    }
1835

    
1836
    public String getFullName() {
1837
        return this.provider.getFullName();
1838
    }
1839

    
1840
    public String getProviderName() {
1841
        return this.provider.getProviderName();
1842
    }
1843

    
1844
    public boolean isKnownEnvelope() {
1845
        return this.provider.isKnownEnvelope();
1846
    }
1847

    
1848
    public boolean hasRetrievedFeaturesLimit() {
1849
        return this.provider.hasRetrievedFeaturesLimit();
1850
    }
1851

    
1852
    public int getRetrievedFeaturesLimit() {
1853
        return this.provider.getRetrievedFeaturesLimit();
1854
    }
1855
}