Statistics
| Revision:

root / branches / dal_time_support / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / featureset / DefaultFeatureSet.java @ 35115

History | View | Annotate | Download (14.5 KB)

1
package org.gvsig.fmap.dal.feature.impl.featureset;
2

    
3
import java.util.ArrayList;
4
import java.util.Collections;
5
import java.util.Iterator;
6
import java.util.List;
7
import java.util.NoSuchElementException;
8

    
9
import org.gvsig.fmap.dal.DataStore;
10
import org.gvsig.fmap.dal.exception.DataException;
11
import org.gvsig.fmap.dal.feature.EditableFeature;
12
import org.gvsig.fmap.dal.feature.Feature;
13
import org.gvsig.fmap.dal.feature.FeatureQuery;
14
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
15
import org.gvsig.fmap.dal.feature.FeatureSet;
16
import org.gvsig.fmap.dal.feature.FeatureStore;
17
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
18
import org.gvsig.fmap.dal.feature.FeatureType;
19
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
20
import org.gvsig.fmap.dal.feature.exception.FeatureSetInitializeException;
21
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureStore;
22
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureStoreTransforms;
23
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
24
import org.gvsig.tools.dispose.DisposableIterator;
25
import org.gvsig.tools.dynobject.DynObjectSet;
26
import org.gvsig.tools.evaluator.Evaluator;
27
import org.gvsig.tools.exception.BaseException;
28
import org.gvsig.tools.observer.Observable;
29
import org.gvsig.tools.observer.Observer;
30
import org.gvsig.tools.visitor.VisitCanceledException;
31
import org.gvsig.tools.visitor.Visitor;
32
import org.gvsig.tools.visitor.impl.AbstractIndexedVisitable;
33

    
34
public class DefaultFeatureSet extends AbstractIndexedVisitable implements
35
                FeatureSet, Observer {
36

    
37

    
38
        private static final int NO_CHECKED = -1;
39
        private static final int DEFAULT = 0;
40
        private static final int FILTERED = 1;
41
        private static final int ORDERED = 2;
42
        private static final int ORDERED_FILTERED = 3;
43
        private static final int EDITED = 4;
44
        private static final int EDITED_FILTERED = 5;
45
        private static final int ORDERD_EDITED = 6;
46
        private static final int ORDERED_EDITED_FILTER = 7;
47

    
48
        private boolean sourceStoreModified;
49
    private boolean ownFeaturesModified;
50
        DefaultFeatureStore store;
51
        private List featureTypes;
52
        FeatureQuery query;
53
        FeatureSetProvider provider;
54
        private long size;
55
        private int iteratorMode;
56
        List orderedData;
57
        private Feature featureToIgnoreNotification;
58
        DefaultFeatureStoreTransforms transform;
59
        private FeatureQuery queryForProvider;
60
        private FeatureType defatulFeatureType;
61
        private FeatureType defatulFeatureTypeForProvider;
62

    
63

    
64
        public DefaultFeatureSet(DefaultFeatureStore store, FeatureQuery query)
65
        throws DataException {
66
                this.featureToIgnoreNotification = null;
67
                this.iteratorMode = NO_CHECKED;
68
                this.sourceStoreModified = false;
69
        this.ownFeaturesModified = false;
70
                this.size = -1;
71
                this.orderedData = null;
72
                this.store = store;
73
                if (this.store.isEditing()) {
74
                        this.transform = this.store.getFeatureTypeManager().getTransforms();
75
                } else {
76
                        this.transform = (DefaultFeatureStoreTransforms) store
77
                                .getTransforms();
78
                }
79
                this.query = query;
80
                try {
81
                        this.queryForProvider = (FeatureQuery) query.clone();
82
                } catch (CloneNotSupportedException e) {
83
                        throw new FeatureSetInitializeException(e);
84
                }
85

    
86
                this.featureTypes = new ArrayList();
87
                if (this.query.getFeatureTypeId() == null
88
                                && this.query.getAttributeNames() == null) {
89
                        this.defatulFeatureType = this.store.getDefaultFeatureType();
90
                        this.featureTypes.addAll(this.store.getFeatureTypes());
91
                } else {
92
                        this.defatulFeatureType = this.store.getFeatureType(this.query);
93
                        this.featureTypes.add(this.defatulFeatureType);
94
                }
95
                if (this.transform != null && !this.transform.isEmpty()) {
96
                        this.fixQueryForProvider(this.queryForProvider, this.transform);
97
                } else {
98
                        this.defatulFeatureTypeForProvider = this.defatulFeatureType;
99
                }
100

    
101
                if (this.queryForProvider.hasFilter() && store.getIndexes() != null) {
102
                        this.provider = (FeatureSetProvider) store.getIndexes()
103
                                        .getFeatureSet(this.queryForProvider.getFilter());
104
                }
105
                if (this.provider == null) {
106
                        this.provider = this.store.getProvider().createSet(
107
                                        this.queryForProvider, this.defatulFeatureTypeForProvider);
108
                }
109
                this.store.addObserver(this);
110
        }
111

    
112
        private void fixQueryForProvider(FeatureQuery theQueryForProvider,
113
                        DefaultFeatureStoreTransforms transformsToUse) throws DataException {
114
                theQueryForProvider.setAttributeNames(null);
115
                FeatureType ftype = transformsToUse
116
                                .getSourceFeatureTypeFrom(this.defatulFeatureType);
117
                theQueryForProvider.setFeatureTypeId(ftype.getId());
118
                this.defatulFeatureTypeForProvider = ftype;
119

    
120
                if (transformsToUse.isTransformsOriginalValues()) {
121
                        theQueryForProvider.setFilter(null);
122
                        theQueryForProvider.getOrder().clear();
123
                        return;
124

    
125
                }
126

    
127
                // Filter
128
                Evaluator filter = theQueryForProvider.getFilter();
129
                if (filter != null) {
130
                        boolean canUseFilter = true;
131
                        if (filter.getFieldsInfo() == null) {
132
                                canUseFilter = false;
133
                        } else {
134
                                canUseFilter = areEvaluatorFieldsInAttributes(filter, ftype);
135
                        }
136

    
137
                        if (!canUseFilter) {
138
                                theQueryForProvider.setFilter(null);
139
                        }
140

    
141
                }
142

    
143

    
144
                // Order
145
                if (theQueryForProvider.hasOrder()){
146
                    boolean canUseOrder = true;
147
                    Iterator iter = theQueryForProvider.getOrder().iterator();
148
                    FeatureQueryOrderMember item;
149
                    while (iter.hasNext()) {
150
                        item = (FeatureQueryOrderMember) iter.next();
151
                        if (item.hasEvaluator()) {
152
                            if (!areEvaluatorFieldsInAttributes(item.getEvaluator(), ftype)) {
153
                                canUseOrder = false;
154
                                break;
155
                            }
156
                        } else {
157
                            if (ftype.get(item.getAttributeName()) == null) {
158
                                canUseOrder = false;
159
                                break;
160
                            }
161
                        }
162
                    }
163

    
164
                    if (!canUseOrder) {
165
                        theQueryForProvider.getOrder().clear();
166
                    }
167
                }
168

    
169
        }
170

    
171
        private boolean areEvaluatorFieldsInAttributes(Evaluator evaluator,
172
                        FeatureType fType) {
173
                if (evaluator.getFieldsInfo() == null) {
174
                        return false;
175
                }
176
                String[] fieldNames = evaluator.getFieldsInfo().getFieldNames();
177
                if (fieldNames.length == 0) {
178
                        return false;
179
                } else {
180
                        for (int i = 0; i < fieldNames.length; i++) {
181
                                if (fType.get(fieldNames[i]) == null) {
182
                                        return false;
183
                                }
184

    
185
                        }
186
                }
187
                return true;
188
        }
189

    
190
        public FeatureType getDefaultFeatureType() {
191
                return this.defatulFeatureType;
192
        }
193

    
194
        public List getFeatureTypes() {
195
                return Collections.unmodifiableList(this.featureTypes);
196
        }
197

    
198
        public long getSize() throws DataException {
199
                this.checkSourceStoreModified();
200
                if (size < 0) {
201
                        size = calculateSize();
202
                }
203
                return size;
204
        }
205

    
206
        private long calculateSize() throws DataException {
207
                int mode = this.getIteratorMode();
208
                if ((mode & EDITED) != EDITED) {
209
                        if( this.provider.isEmpty() ) {
210
                                return 0;
211
                        }
212
                }
213
                if ((mode & FILTERED) == FILTERED) {
214
                        long mySize =0;
215
                        DisposableIterator iter = null;
216
                        try{
217
                                iter = this.fastIterator();
218
                                while (true) {
219
                                        iter.next();
220
                                        mySize++;
221
                                }
222
                        } catch (NoSuchElementException e){
223
                                return mySize;
224
                        } finally {
225
                                iter.dispose();
226
                        }
227
                } else if ((mode & EDITED) == EDITED) {
228
                        return provider.getSize()
229
                        + store.getFeatureManager().getDeltaSize();
230
                }
231
                return provider.getSize();
232
        }
233

    
234
        public void dispose() {
235
                this.store.deleteObserver(this);
236
                this.provider.dispose();
237
                this.provider = null;
238

    
239
                this.featureToIgnoreNotification = null;
240
                if (orderedData != null) {
241
                        orderedData.clear();
242
                }
243
                this.orderedData = null;
244
                this.store = null;
245
                this.transform = null;
246
                this.query = null;
247
                this.queryForProvider = null;
248
                this.featureTypes = null;
249
                this.defatulFeatureType = null;
250
                this.defatulFeatureTypeForProvider = null;
251
        }
252

    
253
        public boolean isFromStore(DataStore store) {
254
                return this.store.equals(store);
255
        }
256

    
257
        public void update(Observable obsevable, Object notification) {
258
                if (sourceStoreModified) {
259
                        return;
260
                }
261

    
262
                String type = ((FeatureStoreNotification) notification).getType();
263

    
264
                if (
265
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
266
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DELETE)
267
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)
268
                ) {
269
                        if( this.featureToIgnoreNotification == ((FeatureStoreNotification) notification).getFeature() ) {
270
                                return;
271
                        }
272
                        sourceStoreModified = true;
273
                        return;
274
                }
275
                if (
276
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE_TYPE)
277
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REDO)
278
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UNDO)
279
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REFRESH)
280
                                || type.equalsIgnoreCase(FeatureStoreNotification.COMPLEX_NOTIFICATION)
281
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CLOSE)
282
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DISPOSE)
283
                                || type.equalsIgnoreCase(FeatureStoreNotification.RESOURCE_CHANGED)
284
                                || type.equalsIgnoreCase(FeatureStoreNotification.TRANSFORM_CHANGE)
285
                ) {
286
                        sourceStoreModified = true;
287
                        return;
288
                }
289
        if (type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CANCELEDITING)
290
            && ownFeaturesModified) {
291
            sourceStoreModified = true;
292
            return;
293
        }
294
        }
295

    
296
        protected void doAccept(Visitor visitor, long firstValueIndex)
297
                        throws VisitCanceledException, BaseException {
298
        DisposableIterator iterator = fastIterator(firstValueIndex);
299

    
300
                try {
301
                        while (iterator.hasNext()) {
302
                                Feature feature = (Feature) iterator.next();
303
                                visitor.visit(feature);
304
                        }
305
                } finally {
306
                        iterator.dispose();
307
                }
308
        }
309

    
310
        protected void checkSourceStoreModified() {
311
                if (sourceStoreModified) {
312
                        throw new ConcurrentDataModificationException(store.getName());
313
                }
314
        }
315

    
316
        public boolean isEmpty() throws DataException {
317
                checkSourceStoreModified();
318
                return this.getSize()==0 ;
319
        }
320

    
321
        public DisposableIterator fastIterator() throws DataException {
322
                return this.fastIterator(0);
323
        }
324

    
325
        public DisposableIterator fastIterator(long index) throws DataException {
326
                if (index < 0) {
327
                        throw new IndexOutOfBoundsException("The index (" + index
328
                                        + ") is less than 0");
329
                }
330
                int mode = this.getIteratorMode();
331

    
332
                switch (mode) {
333
                case DEFAULT:
334
                        return new FastDefaultIterator(this, index);
335

    
336
                case FILTERED:
337
                        return new FastFilteredIterator(this, index);
338

    
339

    
340
                case ORDERED:
341
                        if (this.orderedData != null) {
342
                                return new FastOrderedIterator(this, index);
343
                        } else {
344
                                return new FastOrderedIterator(this, new FastDefaultIterator(
345
                                                this, 0), index);
346
                        }
347

    
348
                case ORDERED_FILTERED:
349
                        if (this.orderedData != null) {
350
                                return new FastOrderedIterator(this, index);
351
                        } else {
352
                                return new FastOrderedIterator(this, new FastFilteredIterator(
353
                                                this, 0), index);
354
                        }
355

    
356
                case EDITED:
357
                        return new FastEditedIterator(this, index);
358

    
359
                case EDITED_FILTERED:
360
                        return new FastEditedFilteredIterator(this, index);
361

    
362
                case ORDERD_EDITED:
363
                        if (this.orderedData != null) {
364
                                return new FastOrderedIterator(this, index);
365
                        } else {
366
                                return new FastOrderedIterator(this, new FastEditedIterator(
367
                                                this, 0), index);
368
                        }
369

    
370
                case ORDERED_EDITED_FILTER:
371
                        if (this.orderedData != null) {
372
                                return new FastOrderedIterator(this, index);
373
                        } else {
374
                                return new FastOrderedIterator(this,
375
                                                new FastEditedFilteredIterator(this, 0), index);
376
                        }
377
                default:
378
                        throw new IllegalArgumentException();
379
                }
380
        }
381

    
382
        public DisposableIterator iterator() throws DataException {
383
                return this.iterator(0);
384
        }
385

    
386
        public DisposableIterator iterator(long index) throws DataException {
387
                if (index < 0) {
388
                        throw new IndexOutOfBoundsException("The index (" + index
389
                                        + ") is less than 0");
390
                }
391
                int mode = this.getIteratorMode();
392

    
393
                switch (mode) {
394
                case DEFAULT:
395
                        return new DefaultIterator(this, index);
396

    
397
                case FILTERED:
398
                        return new FilteredIterator(this, index);
399

    
400
                case ORDERED:
401
                        if (orderedData != null) {
402
                                return new OrderedIterator(this, index);
403

    
404
                        } else {
405
                                return new OrderedIterator(this, new DefaultIterator(this, 0),
406
                                                index);
407
                        }
408

    
409
                case ORDERED_FILTERED:
410
                        return new OrderedIterator(this, new FilteredIterator(this, 0),
411
                                        index);
412

    
413
                case EDITED:
414
                        return new EditedIterator(this, index);
415

    
416
                case EDITED_FILTERED:
417
                        return new EditedFilteredIterator(this, index);
418

    
419
                case ORDERD_EDITED:
420
                        return new OrderedIterator(this,
421
                                        new EditedIterator(this, 0), index);
422

    
423
                case ORDERED_EDITED_FILTER:
424
                        return new OrderedIterator(this,
425
                                        new EditedFilteredIterator(this, 0), index);
426

    
427
                default:
428
                        throw new IllegalArgumentException();
429
                }
430

    
431
        }
432

    
433
        private boolean providerCanOrder() {
434
                return this.provider.canOrder();
435
        }
436

    
437
        private boolean providerCanFilter() {
438
                return this.provider.canFilter();
439
        }
440

    
441
        private int getIteratorMode() {
442

    
443
                if (this.iteratorMode != NO_CHECKED) {
444
                        return this.iteratorMode;
445
                }
446

    
447
                // TODO Tener en cuenta las transformaciones ???
448

    
449
                if (store.isEditing() && store.getFeatureManager().hasChanges()) {
450
                        if (this.query.hasOrder()) { // En edicion siempre ordeno yo.
451
                                if (this.query.hasFilter()) {
452
                                        return ORDERED_EDITED_FILTER;
453
                                } else {
454
                                        return ORDERD_EDITED;
455
                                }
456
                        } else {
457
                                if (this.query.hasFilter()) {
458
                                        return EDITED_FILTERED;
459
                                } else {
460
                                        return EDITED;
461
                                }
462
                        }
463
                } else {
464
                        boolean useMyFilter = this.query.hasFilter();
465
                        boolean useMyOrder = this.query.hasOrder();
466
                        if (this.providerCanOrder() && this.transform.isEmpty()) {
467
                                useMyOrder = false;
468
                        }
469
                        if (this.providerCanFilter() && this.transform.isEmpty()) {
470
                                useMyFilter = false;
471
                        }
472

    
473
                        if (useMyOrder) {
474
                                if (useMyFilter) {
475
                                        return ORDERED_FILTERED;// ORDERED_FILTERED;
476
                                } else {
477
                                        return ORDERED;// ORDERED;
478
                                }
479
                        } else {
480
                                if (useMyFilter) {
481
                                        return FILTERED;// FILTERED;
482
                                } else {
483
                                        return DEFAULT;// DEFAULT;
484
                                }
485
                        }
486
                }
487

    
488
        }
489

    
490
        public void delete(Feature feature) throws DataException {
491
                this.featureToIgnoreNotification = feature;
492
        this.store.delete(feature);
493
                if (this.size > 0) {
494
            this.size--;
495
                }
496
                this.featureToIgnoreNotification = null;
497
        this.ownFeaturesModified = true;
498
        }
499

    
500
        public void insert(EditableFeature feature) throws DataException {
501
                this.featureToIgnoreNotification = feature;
502
                this.store.insert(feature);
503
                if (this.size >= 0) {
504
                        this.size++;
505
                }
506
                this.featureToIgnoreNotification = null;
507
        this.ownFeaturesModified = true;
508
        }
509

    
510
        public void update(EditableFeature feature) throws DataException {
511
                this.featureToIgnoreNotification = feature;
512
                this.store.update(feature);
513
                this.featureToIgnoreNotification = null;
514
        this.ownFeaturesModified = true;
515
        }
516

    
517
    public DynObjectSet getDynObjectSet() {
518
        return this.getDynObjectSet(true);
519
    }
520

    
521
    public DynObjectSet getDynObjectSet(boolean fast) {
522
        return new DynObjectSetFeatureSetFacade(this, store, fast);
523
    }
524

    
525
    public FeatureStore getFeatureStore() {
526
        return store;
527
    }
528
}