Statistics
| Revision:

svn-gvsig-desktop / tags / dal_time_support_Build_1 / libraries / libFMap_dal / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / DefaultFeatureStore.java @ 36109

History | View | Annotate | Download (63.4 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.Collection;
32
import java.util.Collections;
33
import java.util.HashMap;
34
import java.util.HashSet;
35
import java.util.Iterator;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Set;
39
import java.util.Map.Entry;
40

    
41
import org.cresques.cts.IProjection;
42
import org.slf4j.Logger;
43
import org.slf4j.LoggerFactory;
44

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

    
147
public final class DefaultFeatureStore extends AbstractDisposable implements
148
    DataStoreInitializer, FeatureStoreProviderServices, FeatureStore,
149
    Observer {
150

    
151
    final static private Logger logger =
152
        LoggerFactory.getLogger(DefaultFeatureStore.class);
153

    
154
    private static final String PERSISTENCE_DEFINITION_NAME = "FeatureStore";
155

    
156
    private DataStoreParameters parameters = null;
157
    private FeatureSelection selection;
158
    private FeatureLocks locks;
159

    
160
    private DelegateWeakReferencingObservable delegateObservable =
161
        new DelegateWeakReferencingObservable(this);
162

    
163
    private FeatureCommandsStack commands;
164
    private FeatureTypeManager featureTypeManager;
165
    private FeatureManager featureManager;
166
    private SpatialManager spatialManager;
167

    
168
    private FeatureType defaultFeatureType = null;
169
    private List featureTypes = new ArrayList();
170

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

    
176
    private DefaultDataManager dataManager = null;
177

    
178
    private FeatureStoreProvider provider = null;
179

    
180
    private DefaultFeatureIndexes indexes;
181

    
182
    private DefaultFeatureStoreTransforms transforms;
183

    
184
    private DelegatedDynObject metadata;
185
    private Set metadataChildren;
186

    
187
    private Long featureCount = null;
188

    
189
    private long temporalOid = 0;
190

    
191
    private FeatureCacheProvider cache;
192

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

    
202
    public DefaultFeatureStore() {
203

    
204
    }
205

    
206
    public void intializePhase1(DataManager dataManager,
207
        DataStoreParameters parameters) throws InitializeException {
208

    
209
        DynObjectManager dynManager = ToolsLocator.getDynObjectManager();
210

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

    
215
        this.dataManager = (DefaultDataManager)dataManager;
216

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

    
225
    }
226

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

    
234
    public DataStoreParameters getParameters() {
235
        return parameters;
236
    }
237

    
238
    public int getMode() {
239
        return this.mode;
240
    }
241

    
242
    public DataManager getManager() {
243
        return this.dataManager;
244
    }
245

    
246
    public Iterator getChildren() {
247
        return this.provider.getChilds();
248
    }
249

    
250
    public FeatureStoreProvider getProvider() {
251
        return this.provider;
252
    }
253

    
254
    public FeatureManager getFeatureManager() {
255
        return this.featureManager;
256
    }
257

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

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

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

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

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

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

    
307
        this.featureManager = null;
308
        this.spatialManager = null;
309

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

    
318
    public boolean allowWrite() {
319
        return this.provider.allowWrite();
320
    }
321

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

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

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

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

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

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

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

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

    
405
        }
406

    
407
        if (evaluatedAttr.isEmpty()) {
408
            evaluatedAttr = null;
409
        }
410

    
411
        state.set("evaluatedAttributes", evaluatedAttr);
412
        state.set("defaultFeatureTypeId", defaultFeatureType.getId());
413

    
414
    }
415

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

    
425
        DataStoreParameters params =
426
            (DataStoreParameters) state.get("parameters");
427

    
428
        try {
429

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

    
469
                }
470

    
471
            }
472

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

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

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

    
492
    }
493

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

    
504
            definition.addDynFieldObject("parameters").setClassOfValue(
505
                DynObject.class).setMandatory(true).setPersistent(true);
506

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

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

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

    
518
            definition.addDynFieldString("defaultFeatureTypeId").setMandatory(
519
                true).setPersistent(true);
520
        }
521
    }
522

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

    
533
    //
534
    // ====================================================================
535
    // Gestion de la seleccion
536
    //
537

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

    
542
    public DataSet createSelection() throws DataException {
543
        return createFeatureSelection();
544
    }
545

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

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

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

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

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

    
613
        this.notifyChange(DataStoreNotification.SELECTION_CHANGE);
614
    }
615

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

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

    
628
    //
629
    // ====================================================================
630
    // Gestion de notificaciones
631
    //
632

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

    
638
    }
639

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

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

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

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

    
664
    public void notifyChange(FeatureStoreNotification storeNotification) {
665
        delegateObservable.notifyObservers(storeNotification);
666
    }
667

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

    
673
    //
674
    // ====================================================================
675
    // Gestion de bloqueos
676
    //
677

    
678
    public boolean isLocksSupported() {
679
        return this.provider.isLocksSupported();
680
    }
681

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

    
693
    //
694
    // ====================================================================
695
    // Interface Observable
696
    //
697

    
698
    public void disableNotifications() {
699
        this.delegateObservable.disableNotifications();
700

    
701
    }
702

    
703
    public void enableNotifications() {
704
        this.delegateObservable.enableNotifications();
705
    }
706

    
707
    public void beginComplexNotification() {
708
        this.delegateObservable.beginComplexNotification();
709

    
710
    }
711

    
712
    public void endComplexNotification() {
713
        this.delegateObservable.endComplexNotification();
714

    
715
    }
716

    
717
    public void addObserver(Observer observer) {
718
        this.delegateObservable.addObserver(observer);
719

    
720
    }
721

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

    
728
    public void deleteObservers() {
729
        this.delegateObservable.deleteObservers();
730

    
731
    }
732

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

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

    
752
        } else
753
            if (observable instanceof FeatureStoreProvider) {
754
                if (observable == this.provider) {
755

    
756
                }
757

    
758
            }
759
    }
760

    
761
    //
762
    // ====================================================================
763
    // Edicion
764
    //
765

    
766
    private void newVersionOfUpdate() {
767
        this.versionOfUpdate++;
768
    }
769

    
770
    private long currentVersionOfUpdate() {
771
        return this.versionOfUpdate;
772
    }
773

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

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

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

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

    
801
        if (featureTypeManager != null) {
802
            featureTypeManager.dispose();
803
            featureTypeManager = null;
804

    
805
        }
806

    
807
        // TODO implementar un dispose para estos dos
808
        featureManager = null;
809
        spatialManager = null;
810

    
811
        featureCount = null;
812

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

    
818
    synchronized public void edit() throws DataException {
819
        edit(MODE_FULLEDIT);
820
    }
821

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

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

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

    
870
    public boolean isEditing() {
871
        return mode == MODE_FULLEDIT;
872
    }
873

    
874
    public boolean isAppending() {
875
        return mode == MODE_APPEND;
876
    }
877

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

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

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

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

    
919
    private static EditableFeature lastChangedFeature = null;
920

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1111
    public boolean isAppendModeSupported() {
1112
        return this.provider.supportsAppendMode();
1113
    }
1114

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

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

    
1132
            }
1133
            explorer.add(provider, params, true);
1134

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

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

    
1170
    //
1171
    // ====================================================================
1172
    // Obtencion de datos
1173
    // getDataCollection, getFeatureCollection
1174
    //
1175

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

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

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

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

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

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

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

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

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

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

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

    
1251
            private FeatureStore store;
1252
            private FeatureQuery query;
1253
            private Observer observer;
1254

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

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

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

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

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

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

    
1310
            featureType = this.transforms.getSourceFeatureTypeFrom(featureType);
1311

    
1312
        }
1313
        // TODO comprobar que el id es de este store
1314

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

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

    
1332
    //
1333
    // ====================================================================
1334
    // Gestion de features
1335
    //
1336

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

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

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

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

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

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

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

    
1411
        }
1412

    
1413
        return type;
1414
    }
1415

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

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

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

    
1487
    public FeatureType getProviderDefaultFeatureType() {
1488
        return defaultFeatureType;
1489
    }
1490

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

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

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

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

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

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

    
1567
    }
1568

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

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

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

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

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

    
1604
    //
1605
    // ====================================================================
1606
    // Index related methods
1607
    //
1608

    
1609
    public FeatureIndexes getIndexes() {
1610
        return this.indexes;
1611
    }
1612

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

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

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

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

    
1649
    //
1650
    // ====================================================================
1651
    // Transforms related methods
1652
    //
1653

    
1654
    public FeatureStoreTransforms getTransforms() {
1655
        return this.transforms;
1656
    }
1657

    
1658
    public FeatureQuery createFeatureQuery() {
1659
        return new DefaultFeatureQuery();
1660
    }
1661

    
1662
    public DataQuery createQuery() {
1663
        return createFeatureQuery();
1664
    }
1665

    
1666
    //
1667
    // ====================================================================
1668
    // UndoRedo related methods
1669
    //
1670

    
1671
    public boolean canRedo() {
1672
        return commands.canRedo();
1673
    }
1674

    
1675
    public boolean canUndo() {
1676
        return commands.canUndo();
1677
    }
1678

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

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

    
1687
    //
1688
    // ====================================================================
1689
    // Metadata related methods
1690
    //
1691

    
1692
    public Object getMetadataID() {
1693
        return this.provider.getSourceId();
1694
    }
1695

    
1696
    public void delegate(DynObject dynObject) {
1697
        this.metadata.delegate(dynObject);
1698
    }
1699

    
1700
    public DynClass getDynClass() {
1701
        return this.metadata.getDynClass();
1702
    }
1703

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

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

    
1728
    public void implement(DynClass dynClass) {
1729
        this.metadata.implement(dynClass);
1730
    }
1731

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

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

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

    
1746
    }
1747

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

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

    
1766
    public FeatureTypeManager getFeatureTypeManager() {
1767
        return this.featureTypeManager;
1768
    }
1769

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

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

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

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

    
1804
    public DataStore getStore() {
1805
        return this;
1806
    }
1807

    
1808
    public FeatureStore getFeatureStore() {
1809
        return this;
1810
    }
1811

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

    
1821
        featureCount = null;
1822
    }
1823

    
1824
    public FeatureCache getCache() {
1825
        return cache;
1826
    }
1827

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

    
1834
    public String getName() {
1835
        return this.provider.getName();
1836
    }
1837

    
1838
    public String getFullName() {
1839
        return this.provider.getFullName();
1840
    }
1841

    
1842
    public String getProviderName() {
1843
        return this.provider.getProviderName();
1844
    }
1845

    
1846
    public boolean isKnownEnvelope() {
1847
        return this.provider.isKnownEnvelope();
1848
    }
1849

    
1850
    public boolean hasRetrievedFeaturesLimit() {
1851
        return this.provider.hasRetrievedFeaturesLimit();
1852
    }
1853

    
1854
    public int getRetrievedFeaturesLimit() {
1855
        return this.provider.getRetrievedFeaturesLimit();
1856
    }
1857

    
1858
    public Interval getInterval() {  
1859
        return this.provider.getInterval();
1860
    }
1861

    
1862
    public Collection getTimes() {      
1863
        return this.provider.getTimes();
1864
    }
1865

    
1866
    public Collection getTimes(Interval interval) {       
1867
        return this.provider.getTimes(interval);
1868
    }
1869
}