Statistics
| Revision:

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

History | View | Annotate | Download (13.1 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.DisposableIterator;
12
import org.gvsig.fmap.dal.feature.EditableFeature;
13
import org.gvsig.fmap.dal.feature.Feature;
14
import org.gvsig.fmap.dal.feature.FeatureQuery;
15
import org.gvsig.fmap.dal.feature.FeatureSet;
16
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
17
import org.gvsig.fmap.dal.feature.FeatureType;
18
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
19
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
20
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureStore;
21
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureStoreTransforms;
22
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
23
import org.gvsig.tools.evaluator.Evaluator;
24
import org.gvsig.tools.exception.BaseException;
25
import org.gvsig.tools.observer.Observable;
26
import org.gvsig.tools.observer.Observer;
27
import org.gvsig.tools.visitor.Visitor;
28

    
29
public class DefaultFeatureSet implements FeatureSet, Observer {
30

    
31

    
32
        private static final int NO_CHECKED = -1;
33
        private static final int DEFAULT = 0;
34
        private static final int FILTERED = 1;
35
        private static final int ORDERED = 2;
36
        private static final int ORDERED_FILTERED = 3;
37
        private static final int EDITED = 4;
38
        private static final int EDITED_FILTERED = 5;
39
        private static final int ORDERD_EDITED = 6;
40
        private static final int ORDERED_EDITED_FILTER = 7;
41

    
42
        private boolean modified;
43
        DefaultFeatureStore store;
44
        private List featureTypes;
45
        FeatureQuery query;
46
        FeatureSetProvider provider;
47
        private long size;
48
        private int iteratorMode;
49
        List orderedData;
50
        private Feature featureToIgnoreNotification;
51
        private List providerFeatureTypes;
52
        DefaultFeatureStoreTransforms transform;
53
        private FeatureQuery queryForProvider;
54
        private FeatureType defatulFeatureType;
55
        private FeatureType defatulFeatureTypeForProvider;
56

    
57

    
58
        public DefaultFeatureSet(DefaultFeatureStore store, FeatureQuery query)
59
        throws DataException {
60
                this.featureToIgnoreNotification = null;
61
                this.iteratorMode = NO_CHECKED;
62
                this.modified = false;
63
                this.size = -1;
64
                this.orderedData = null;
65
                this.store = store;
66
                if (this.store.isEditing()) {
67
                        this.transform = this.store.getFeatureTypeManager().getTransforms();
68
                } else {
69
                        this.transform = (DefaultFeatureStoreTransforms) store
70
                                .getTransforms();
71
                }
72
                this.query = query;
73
                this.queryForProvider = query.getCopy();
74

    
75
                this.featureTypes = new ArrayList();
76
                if (this.query.getFeatureTypeId() == null
77
                                && this.query.getAttributeNames() == null) {
78
                        this.defatulFeatureType = this.store.getDefaultFeatureType();
79
                        this.featureTypes.addAll(this.store.getFeatureTypes());
80
                } else {
81
                        this.defatulFeatureType = this.store.getFeatureType(this.query);
82
                        this.featureTypes.add(this.defatulFeatureType);
83
                }
84
                if (!this.transform.isEmpty()) {
85
                        this.fixQueryForProvider(this.queryForProvider, this.transform);
86
                } else {
87
                        this.defatulFeatureTypeForProvider = this.defatulFeatureType;
88
                }
89

    
90
                if (query.hasFilter() && store.getIndexes() != null) {
91
                        this.provider = (FeatureSetProvider) store.getIndexes()
92
                        .getFeatureSet(this.queryForProvider.getFilter());
93
                }
94
                if (this.provider == null) {
95
                        this.provider = this.store.getProvider().createSet(
96
                                        this.queryForProvider, this.defatulFeatureTypeForProvider);
97
                }
98
                this.store.addObserver(this);
99
        }
100

    
101
        private void fixQueryForProvider(FeatureQuery theQueryForProvider,
102
                        DefaultFeatureStoreTransforms transformsToUse) throws DataException {
103
                theQueryForProvider.setAttributeNames(null);
104
                FeatureType ftype = transformsToUse
105
                                .getSourceFeatureTypeFrom(this.defatulFeatureType);
106
                theQueryForProvider.setFeatureTypeId(ftype.getId());
107
                this.defatulFeatureTypeForProvider = ftype;
108

    
109
                if (transformsToUse.isTransformsOriginalValues()) {
110
                        theQueryForProvider.setFilter(null);
111
                        theQueryForProvider.getOrder().clear();
112
                        return;
113

    
114
                }
115

    
116
                // Filter
117
                Evaluator filter = theQueryForProvider.getFilter();
118
                if (filter != null) {
119
                        boolean canUseFilter = true;
120
                        if (filter.getFieldsInfo() == null) {
121
                                canUseFilter = false;
122
                        } else {
123
                                canUseFilter = areEvaluatorFieldsInAttributes(filter, ftype);
124
                        }
125

    
126
                        if (!canUseFilter) {
127
                                theQueryForProvider.setFilter(null);
128
                        }
129

    
130
                }
131

    
132

    
133
                // Order
134
                boolean canUseOrder = true;
135
                Iterator iter = theQueryForProvider.getOrder().iterator();
136
                FeatureQueryOrderMember item;
137
                while (iter.hasNext()) {
138
                        item = (FeatureQueryOrderMember) iter.next();
139
                        if (item.hasEvaluator()) {
140
                                if (!areEvaluatorFieldsInAttributes(item.getEvaluator(), ftype)) {
141
                                        canUseOrder = false;
142
                                        break;
143
                                }
144
                        } else {
145
                                if (ftype.get(item.getAttributeName()) == null) {
146
                                        canUseOrder = false;
147
                                        break;
148
                                }
149
                        }
150
                }
151

    
152
                if (!canUseOrder) {
153
                        theQueryForProvider.getOrder().clear();
154
                }
155

    
156

    
157
        }
158

    
159
        private boolean areEvaluatorFieldsInAttributes(Evaluator evaluator,
160
                        FeatureType fType) {
161
                if (evaluator.getFieldsInfo() == null) {
162
                        return false;
163
                }
164
                String[] fieldNames = evaluator.getFieldsInfo().getFieldNames();
165
                if (fieldNames.length == 0) {
166
                        return false;
167
                } else {
168
                        for (int i = 0; i < fieldNames.length; i++) {
169
                                if (fType.get(fieldNames[i]) == null) {
170
                                        return false;
171
                                }
172

    
173
                        }
174
                }
175
                return true;
176
        }
177

    
178
        public FeatureType getDefaultFeatureType() {
179
                return this.defatulFeatureType;
180
        }
181

    
182
        public List getFeatureTypes() {
183
                return Collections.unmodifiableList(this.featureTypes);
184
        }
185

    
186
        public long getSize() throws DataException {
187
                this.checkModified();
188
                if (size < 0) {
189
                        size = calculateSize();
190
                }
191
                return size;
192
        }
193

    
194
        private long calculateSize() throws DataException {
195
                int mode = this.getIteratorMode();
196
                if ((mode & FILTERED) == FILTERED) {
197
                        long mySize =0;
198
                        Iterator iter = this.fastIterator();
199
                        try{
200
                                while (true) {
201
                                        iter.next();
202
                                        mySize++;
203
                                }
204
                        } catch (NoSuchElementException e){
205
                                return mySize;
206
                        }
207
                } else if ((mode & EDITED) == EDITED) {
208
                        return provider.getSize()
209
                        + store.getFeatureManager().getDeltaSize();
210
                }
211
                return provider.getSize();
212
        }
213

    
214
        public void dispose() {
215
                this.store.deleteObserver(this);
216
                this.provider.dispose();
217
                this.provider = null;
218

    
219
                this.featureToIgnoreNotification = null;
220
                if (orderedData != null) {
221
                        orderedData.clear();
222
                }
223
                this.orderedData = null;
224
                this.store = null;
225
                this.transform = null;
226
                this.query = null;
227
                this.queryForProvider = null;
228
                this.featureTypes = null;
229
                this.providerFeatureTypes = null;
230
                this.defatulFeatureType = null;
231
                this.defatulFeatureTypeForProvider = null;
232

    
233

    
234
        }
235

    
236
        public boolean isFromStore(DataStore store) {
237
                return this.store.equals(store);
238
        }
239

    
240
        public void update(Observable obsevable, Object notification) {
241
                if (modified) {
242
                        return;
243
                }
244

    
245
                String type = ((FeatureStoreNotification) notification).getType();
246

    
247
                if (
248
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
249
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DELETE)
250
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)
251
                ) {
252
                        if( this.featureToIgnoreNotification == ((FeatureStoreNotification) notification).getFeature() ) {
253
                                return;
254
                        }
255
                        modified = true;
256
                        return;
257
                }
258
                if (
259
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE_TYPE)
260
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REDO)
261
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UNDO)
262
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CANCELEDITING)
263
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REFRESH)
264
                                || type.equalsIgnoreCase(FeatureStoreNotification.COMPLEX_NOTIFICATION)
265
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CLOSE)
266
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DISPOSE)
267
                                || type.equalsIgnoreCase(FeatureStoreNotification.RESOURCE_CHANGED)
268
                                || type.equalsIgnoreCase(FeatureStoreNotification.TRANSFORM_CHANGE)
269
                ) {
270
                        modified = true;
271
                        return;
272
                }
273
        }
274

    
275
        public void accept(Visitor visitor) throws BaseException {
276
                Iterator iterator = iterator();
277

    
278
                while (iterator.hasNext()) {
279
                        Feature feature = (Feature) iterator.next();
280
                        visitor.visit(feature);
281
                }
282
        }
283

    
284
        protected void checkModified() {
285
                if (modified) {
286
                        throw new ConcurrentDataModificationException(store.getName());
287
                }
288
        }
289

    
290
        public boolean isEmpty() throws DataException {
291
                checkModified();
292
                if (this.store.isEditing()) {
293
                        if (this.store.getFeatureManager().hasNews()) {
294
                                return false;
295
                        }
296
                        if (this.provider.isEmpty()) {
297
                                return true;
298
                        }
299
                        return this.provider.getSize()
300
                        + this.store.getFeatureManager().getDeltaSize() == 0;
301
                }
302
                return this.provider.isEmpty();
303
        }
304

    
305
        public DisposableIterator fastIterator() throws DataException {
306
                return this.fastIterator(0);
307
        }
308

    
309
        public DisposableIterator fastIterator(long index) throws DataException {
310
                if (index < 0) {
311
                        throw new IndexOutOfBoundsException("The index (" + index
312
                                        + ") is less than 0");
313
                }
314
                int mode = this.getIteratorMode();
315

    
316
                switch (mode) {
317
                case DEFAULT:
318
                        return new FastDefaultIterator(this, index);
319

    
320
                case FILTERED:
321
                        return new FastFilteredIterator(this, index);
322

    
323

    
324
                case ORDERED:
325
                        if (this.orderedData != null) {
326
                                return new FastOrderedIterator(this, index);
327
                        } else {
328
                                return new FastOrderedIterator(this, new FastDefaultIterator(
329
                                                this, 0), index);
330
                        }
331

    
332
                case ORDERED_FILTERED:
333
                        if (this.orderedData != null) {
334
                                return new FastOrderedIterator(this, index);
335
                        } else {
336
                                return new FastOrderedIterator(this, new FastFilteredIterator(
337
                                                this, 0), index);
338
                        }
339

    
340
                case EDITED:
341
                        return new FastEditedIterator(this, index);
342

    
343
                case EDITED_FILTERED:
344
                        return new FastEditedFilteredIterator(this, index);
345

    
346
                case ORDERD_EDITED:
347
                        if (this.orderedData != null) {
348
                                return new FastOrderedIterator(this, index);
349
                        } else {
350
                                return new FastOrderedIterator(this, new FastEditedIterator(
351
                                                this, 0), index);
352
                        }
353

    
354
                case ORDERED_EDITED_FILTER:
355
                        if (this.orderedData != null) {
356
                                return new FastOrderedIterator(this, index);
357
                        } else {
358
                                return new FastOrderedIterator(this,
359
                                                new FastEditedFilteredIterator(this, 0), index);
360
                        }
361
                default:
362
                        throw new IllegalArgumentException();
363
                }
364
        }
365

    
366
        public DisposableIterator iterator() throws DataException {
367
                return this.iterator(0);
368
        }
369

    
370
        public DisposableIterator iterator(long index) throws DataException {
371
                if (index < 0) {
372
                        throw new IndexOutOfBoundsException("The index (" + index
373
                                        + ") is less than 0");
374
                }
375
                int mode = this.getIteratorMode();
376

    
377
                switch (mode) {
378
                case DEFAULT:
379
                        return new DefaultIterator(this, index);
380

    
381
                case FILTERED:
382
                        return new FilteredIterator(this, index);
383

    
384
                case ORDERED:
385
                        if (orderedData != null) {
386
                                return new OrderedIterator(this, index);
387

    
388
                        } else {
389
                                return new OrderedIterator(this, new DefaultIterator(this, 0),
390
                                                index);
391
                        }
392

    
393
                case ORDERED_FILTERED:
394
                        return new OrderedIterator(this, new FilteredIterator(this, 0),
395
                                        index);
396

    
397
                case EDITED:
398
                        return new EditedIterator(this, index);
399

    
400
                case EDITED_FILTERED:
401
                        return new EditedFilteredIterator(this, index);
402

    
403
                case ORDERD_EDITED:
404
                        return new OrderedIterator(this,
405
                                        new EditedIterator(this, 0), index);
406

    
407
                case ORDERED_EDITED_FILTER:
408
                        return new OrderedIterator(this,
409
                                        new EditedFilteredIterator(this, 0), index);
410

    
411
                default:
412
                        throw new IllegalArgumentException();
413
                }
414

    
415
        }
416

    
417
        private boolean providerCanOrder() {
418
                return this.provider.canOrder();
419
        }
420

    
421
        private boolean providerCanFilter() {
422
                return this.provider.canFilter();
423
        }
424

    
425
        private int getIteratorMode() {
426

    
427
                if (this.iteratorMode != NO_CHECKED) {
428
                        return this.iteratorMode;
429
                }
430

    
431
                // TODO Tener en cuenta las transformaciones ???
432

    
433
                if (store.isEditing() && store.getFeatureManager().hasChanges()) {
434
                        if (this.query.hasOrder()) { // En edicion siempre ordeno yo.
435
                                if (this.query.hasFilter()) {
436
                                        return ORDERED_EDITED_FILTER;
437
                                } else {
438
                                        return ORDERD_EDITED;
439
                                }
440
                        } else {
441
                                if (this.query.hasFilter()) {
442
                                        return EDITED_FILTERED;
443
                                } else {
444
                                        return EDITED;
445
                                }
446
                        }
447
                } else {
448
                        boolean useMyFilter = this.query.hasFilter();
449
                        boolean useMyOrder = this.query.hasOrder();
450
                        if (this.providerCanOrder() && this.transform.isEmpty()) {
451
                                useMyOrder = false;
452
                        }
453
                        if (this.providerCanFilter() && this.transform.isEmpty()) {
454
                                useMyFilter = false;
455
                        }
456

    
457
                        if (useMyOrder) {
458
                                if (useMyFilter) {
459
                                        return ORDERED_FILTERED;// ORDERED_FILTERED;
460
                                } else {
461
                                        return ORDERED;// ORDERED;
462
                                }
463
                        } else {
464
                                if (useMyFilter) {
465
                                        return FILTERED;// FILTERED;
466
                                } else {
467
                                        return DEFAULT;// DEFAULT;
468
                                }
469
                        }
470
                }
471

    
472
        }
473

    
474
        public void delete(Feature feature) throws DataException {
475
                this.featureToIgnoreNotification = feature;
476
                this.store.delete(feature);
477
                if (this.size > 0) {
478
                        this.size--;
479
                }
480
                this.featureToIgnoreNotification = null;
481
        }
482

    
483
        public void insert(EditableFeature feature) throws DataException {
484
                this.featureToIgnoreNotification = feature;
485
                this.store.insert(feature);
486
                if (this.size >= 0) {
487
                        this.size++;
488
                }
489
                this.featureToIgnoreNotification = null;
490
        }
491

    
492
        public void update(EditableFeature feature) throws DataException {
493
                this.featureToIgnoreNotification = feature;
494
                this.store.update(feature);
495
                this.featureToIgnoreNotification = null;
496
        }
497

    
498
}