Statistics
| Revision:

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

History | View | Annotate | Download (13.4 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.FeatureSet;
15
import org.gvsig.fmap.dal.feature.FeatureStoreNotification;
16
import org.gvsig.fmap.dal.feature.FeatureType;
17
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
18
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
19
import org.gvsig.fmap.dal.feature.exception.FeatureSetInitializeException;
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.dispose.DisposableIterator;
24
import org.gvsig.tools.evaluator.Evaluator;
25
import org.gvsig.tools.exception.BaseException;
26
import org.gvsig.tools.observer.Observable;
27
import org.gvsig.tools.observer.Observer;
28
import org.gvsig.tools.visitor.VisitCanceledException;
29
import org.gvsig.tools.visitor.Visitor;
30
import org.gvsig.tools.visitor.impl.AbstractIndexedVisitable;
31

    
32
public class DefaultFeatureSet extends AbstractIndexedVisitable implements
33
                FeatureSet, Observer {
34

    
35

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

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

    
60

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

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

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

    
108
        private void fixQueryForProvider(FeatureQuery theQueryForProvider,
109
                        DefaultFeatureStoreTransforms transformsToUse) throws DataException {
110
                theQueryForProvider.setAttributeNames(null);
111
                FeatureType ftype = transformsToUse
112
                                .getSourceFeatureTypeFrom(this.defatulFeatureType);
113
                theQueryForProvider.setFeatureTypeId(ftype.getId());
114
                this.defatulFeatureTypeForProvider = ftype;
115

    
116
                if (transformsToUse.isTransformsOriginalValues()) {
117
                        theQueryForProvider.setFilter(null);
118
                        theQueryForProvider.getOrder().clear();
119
                        return;
120

    
121
                }
122

    
123
                // Filter
124
                Evaluator filter = theQueryForProvider.getFilter();
125
                if (filter != null) {
126
                        boolean canUseFilter = true;
127
                        if (filter.getFieldsInfo() == null) {
128
                                canUseFilter = false;
129
                        } else {
130
                                canUseFilter = areEvaluatorFieldsInAttributes(filter, ftype);
131
                        }
132

    
133
                        if (!canUseFilter) {
134
                                theQueryForProvider.setFilter(null);
135
                        }
136

    
137
                }
138

    
139

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

    
159
                if (!canUseOrder) {
160
                        theQueryForProvider.getOrder().clear();
161
                }
162

    
163

    
164
        }
165

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

    
180
                        }
181
                }
182
                return true;
183
        }
184

    
185
        public FeatureType getDefaultFeatureType() {
186
                return this.defatulFeatureType;
187
        }
188

    
189
        public List getFeatureTypes() {
190
                return Collections.unmodifiableList(this.featureTypes);
191
        }
192

    
193
        public long getSize() throws DataException {
194
                this.checkModified();
195
                if (size < 0) {
196
                        size = calculateSize();
197
                }
198
                return size;
199
        }
200

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

    
229
        public void dispose() {
230
                this.store.deleteObserver(this);
231
                this.provider.dispose();
232
                this.provider = null;
233

    
234
                this.featureToIgnoreNotification = null;
235
                if (orderedData != null) {
236
                        orderedData.clear();
237
                }
238
                this.orderedData = null;
239
                this.store = null;
240
                this.transform = null;
241
                this.query = null;
242
                this.queryForProvider = null;
243
                this.featureTypes = null;
244
                this.defatulFeatureType = null;
245
                this.defatulFeatureTypeForProvider = null;
246
        }
247

    
248
        public boolean isFromStore(DataStore store) {
249
                return this.store.equals(store);
250
        }
251

    
252
        public void update(Observable obsevable, Object notification) {
253
                if (modified) {
254
                        return;
255
                }
256

    
257
                String type = ((FeatureStoreNotification) notification).getType();
258

    
259
                if (
260
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
261
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DELETE)
262
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)
263
                ) {
264
                        if( this.featureToIgnoreNotification == ((FeatureStoreNotification) notification).getFeature() ) {
265
                                return;
266
                        }
267
                        modified = true;
268
                        return;
269
                }
270
                if (
271
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE_TYPE)
272
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REDO)
273
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UNDO)
274
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CANCELEDITING)
275
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REFRESH)
276
                                || type.equalsIgnoreCase(FeatureStoreNotification.COMPLEX_NOTIFICATION)
277
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CLOSE)
278
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DISPOSE)
279
                                || type.equalsIgnoreCase(FeatureStoreNotification.RESOURCE_CHANGED)
280
                                || type.equalsIgnoreCase(FeatureStoreNotification.TRANSFORM_CHANGE)
281
                ) {
282
                        modified = true;
283
                        return;
284
                }
285
        }
286

    
287
        protected void doAccept(Visitor visitor, long firstValueIndex)
288
                        throws VisitCanceledException, BaseException {
289
                DisposableIterator iterator = iterator(firstValueIndex);
290

    
291
                try {
292
                        while (iterator.hasNext()) {
293
                                Feature feature = (Feature) iterator.next();
294
                                visitor.visit(feature);
295
                        }
296
                } finally {
297
                        iterator.dispose();
298
                }
299
        }
300

    
301
        protected void checkModified() {
302
                if (modified) {
303
                        throw new ConcurrentDataModificationException(store.getName());
304
                }
305
        }
306

    
307
        public boolean isEmpty() throws DataException {
308
                checkModified();
309
                return this.getSize()==0 ;
310
        }
311

    
312
        public DisposableIterator fastIterator() throws DataException {
313
                return this.fastIterator(0);
314
        }
315

    
316
        public DisposableIterator fastIterator(long index) throws DataException {
317
                if (index < 0) {
318
                        throw new IndexOutOfBoundsException("The index (" + index
319
                                        + ") is less than 0");
320
                }
321
                int mode = this.getIteratorMode();
322

    
323
                switch (mode) {
324
                case DEFAULT:
325
                        return new FastDefaultIterator(this, index);
326

    
327
                case FILTERED:
328
                        return new FastFilteredIterator(this, index);
329

    
330

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

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

    
347
                case EDITED:
348
                        return new FastEditedIterator(this, index);
349

    
350
                case EDITED_FILTERED:
351
                        return new FastEditedFilteredIterator(this, index);
352

    
353
                case ORDERD_EDITED:
354
                        if (this.orderedData != null) {
355
                                return new FastOrderedIterator(this, index);
356
                        } else {
357
                                return new FastOrderedIterator(this, new FastEditedIterator(
358
                                                this, 0), index);
359
                        }
360

    
361
                case ORDERED_EDITED_FILTER:
362
                        if (this.orderedData != null) {
363
                                return new FastOrderedIterator(this, index);
364
                        } else {
365
                                return new FastOrderedIterator(this,
366
                                                new FastEditedFilteredIterator(this, 0), index);
367
                        }
368
                default:
369
                        throw new IllegalArgumentException();
370
                }
371
        }
372

    
373
        public DisposableIterator iterator() throws DataException {
374
                return this.iterator(0);
375
        }
376

    
377
        public DisposableIterator iterator(long index) throws DataException {
378
                if (index < 0) {
379
                        throw new IndexOutOfBoundsException("The index (" + index
380
                                        + ") is less than 0");
381
                }
382
                int mode = this.getIteratorMode();
383

    
384
                switch (mode) {
385
                case DEFAULT:
386
                        return new DefaultIterator(this, index);
387

    
388
                case FILTERED:
389
                        return new FilteredIterator(this, index);
390

    
391
                case ORDERED:
392
                        if (orderedData != null) {
393
                                return new OrderedIterator(this, index);
394

    
395
                        } else {
396
                                return new OrderedIterator(this, new DefaultIterator(this, 0),
397
                                                index);
398
                        }
399

    
400
                case ORDERED_FILTERED:
401
                        return new OrderedIterator(this, new FilteredIterator(this, 0),
402
                                        index);
403

    
404
                case EDITED:
405
                        return new EditedIterator(this, index);
406

    
407
                case EDITED_FILTERED:
408
                        return new EditedFilteredIterator(this, index);
409

    
410
                case ORDERD_EDITED:
411
                        return new OrderedIterator(this,
412
                                        new EditedIterator(this, 0), index);
413

    
414
                case ORDERED_EDITED_FILTER:
415
                        return new OrderedIterator(this,
416
                                        new EditedFilteredIterator(this, 0), index);
417

    
418
                default:
419
                        throw new IllegalArgumentException();
420
                }
421

    
422
        }
423

    
424
        private boolean providerCanOrder() {
425
                return this.provider.canOrder();
426
        }
427

    
428
        private boolean providerCanFilter() {
429
                return this.provider.canFilter();
430
        }
431

    
432
        private int getIteratorMode() {
433

    
434
                if (this.iteratorMode != NO_CHECKED) {
435
                        return this.iteratorMode;
436
                }
437

    
438
                // TODO Tener en cuenta las transformaciones ???
439

    
440
                if (store.isEditing() && store.getFeatureManager().hasChanges()) {
441
                        if (this.query.hasOrder()) { // En edicion siempre ordeno yo.
442
                                if (this.query.hasFilter()) {
443
                                        return ORDERED_EDITED_FILTER;
444
                                } else {
445
                                        return ORDERD_EDITED;
446
                                }
447
                        } else {
448
                                if (this.query.hasFilter()) {
449
                                        return EDITED_FILTERED;
450
                                } else {
451
                                        return EDITED;
452
                                }
453
                        }
454
                } else {
455
                        boolean useMyFilter = this.query.hasFilter();
456
                        boolean useMyOrder = this.query.hasOrder();
457
                        if (this.providerCanOrder() && this.transform.isEmpty()) {
458
                                useMyOrder = false;
459
                        }
460
                        if (this.providerCanFilter() && this.transform.isEmpty()) {
461
                                useMyFilter = false;
462
                        }
463

    
464
                        if (useMyOrder) {
465
                                if (useMyFilter) {
466
                                        return ORDERED_FILTERED;// ORDERED_FILTERED;
467
                                } else {
468
                                        return ORDERED;// ORDERED;
469
                                }
470
                        } else {
471
                                if (useMyFilter) {
472
                                        return FILTERED;// FILTERED;
473
                                } else {
474
                                        return DEFAULT;// DEFAULT;
475
                                }
476
                        }
477
                }
478

    
479
        }
480

    
481
        public void delete(Feature feature) throws DataException {
482
                this.featureToIgnoreNotification = feature;
483
                this.store.delete(feature);
484
                if (this.size > 0) {
485
                        this.size--;
486
                }
487
                this.featureToIgnoreNotification = null;
488
        }
489

    
490
        public void insert(EditableFeature feature) throws DataException {
491
                this.featureToIgnoreNotification = feature;
492
                this.store.insert(feature);
493
                if (this.size >= 0) {
494
                        this.size++;
495
                }
496
                this.featureToIgnoreNotification = null;
497
        }
498

    
499
        public void update(EditableFeature feature) throws DataException {
500
                this.featureToIgnoreNotification = feature;
501
                this.store.update(feature);
502
                this.featureToIgnoreNotification = null;
503
        }
504

    
505
}