Statistics
| Revision:

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

History | View | Annotate | Download (12.2 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.impl.DefaultFeatureStore;
20
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureStoreTransforms;
21
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
22
import org.gvsig.tools.evaluator.Evaluator;
23
import org.gvsig.tools.exception.BaseException;
24
import org.gvsig.tools.observer.Observable;
25
import org.gvsig.tools.observer.Observer;
26
import org.gvsig.tools.visitor.Visitor;
27

    
28
public class DefaultFeatureSet implements FeatureSet, Observer {
29

    
30

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

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

    
55

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

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

    
86
                if (query.hasFilter() && store.getIndexes() != null) {
87
                        this.provider = (FeatureSetProvider) store.getIndexes()
88
                        .getFeatureSet(this.queryForProvider.getFilter());
89
                }
90
                if (this.provider == null) {
91
                        this.provider = this.store.getProvider().createSet(
92
                                        this.queryForProvider);
93
                }
94
                this.store.addObserver(this);
95
        }
96

    
97
        private void fixQueryForProvider(FeatureQuery theQueryForProvider,
98
                        DefaultFeatureStoreTransforms transformsToUse) throws DataException {
99
                theQueryForProvider.setAttributeNames(null);
100
                FeatureType ftype = transformsToUse.getSourceFeatureTypeFrom(this.store
101
                                .getFeatureType(theQueryForProvider.getFeatureTypeId()));
102
                theQueryForProvider
103
                                .setFeatureTypeId(ftype.getId());
104

    
105
                if (transformsToUse.isTransformsOriginalValues()) {
106
                        theQueryForProvider.setFilter(null);
107
                        theQueryForProvider.getOrder().clear();
108
                        return;
109

    
110
                }
111

    
112
                // Filter
113
                Evaluator filter = theQueryForProvider.getFilter();
114
                if (filter != null) {
115
                        boolean canUseFilter = true;
116
                        if (filter.getFieldsInfo() == null) {
117
                                canUseFilter = false;
118
                        } else {
119
                                canUseFilter = areEvaluatorFieldsInAttributes(filter, ftype);
120
                        }
121

    
122
                        if (!canUseFilter) {
123
                                theQueryForProvider.setFilter(null);
124
                        }
125

    
126
                }
127

    
128

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

    
148
                if (!canUseOrder) {
149
                        theQueryForProvider.getOrder().clear();
150
                }
151

    
152

    
153
        }
154

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

    
169
                        }
170
                }
171
                return true;
172
        }
173

    
174
        public FeatureType getDefaultFeatureType() {
175
                return this.defatulFeatureType;
176
        }
177

    
178
        public List getFeatureTypes() {
179
                return Collections.unmodifiableList(this.featureTypes);
180
        }
181

    
182
        public long getSize() throws DataException {
183
                this.checkModified();
184
                if (size < 0) {
185
                        size = calculateSize();
186
                }
187
                return size;
188
        }
189

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

    
210
        public void dispose() {
211
                this.store.deleteObserver(this);
212
                this.provider = null;
213

    
214
                this.featureToIgnoreNotification = null;
215
                this.orderedData = null;
216
                this.store = null;
217
                this.transform = null;
218
                this.query = null;
219
                this.queryForProvider = null;
220
                this.featureTypes = null;
221

    
222
        }
223

    
224
        public boolean isFromStore(DataStore store) {
225
                return this.store.equals(store);
226
        }
227

    
228
        public void update(Observable obsevable, Object notification) {
229
                if (modified) {
230
                        return;
231
                }
232

    
233
                String type = ((FeatureStoreNotification) notification).getType();
234

    
235
                if (
236
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
237
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DELETE)
238
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)
239
                ) {
240
                        if( this.featureToIgnoreNotification == ((FeatureStoreNotification) notification).getFeature() ) {
241
                                return;
242
                        }
243
                        modified = true;
244
                        return;
245
                }
246
                if (
247
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE_TYPE)
248
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REDO)
249
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UNDO)
250
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CANCELEDITING)
251
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REFRESH)
252
                                || type.equalsIgnoreCase(FeatureStoreNotification.COMPLEX_NOTIFICATION)
253
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CLOSE)
254
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DISPOSE)
255
                                || type.equalsIgnoreCase(FeatureStoreNotification.RESOURCE_CHANGED)
256
                                || type.equalsIgnoreCase(FeatureStoreNotification.TRANSFORM_CHANGE)
257
                ) {
258
                        modified = true;
259
                        return;
260
                }
261
        }
262

    
263
        public void accept(Visitor visitor) throws BaseException {
264
                Iterator iterator = iterator();
265

    
266
                while (iterator.hasNext()) {
267
                        Feature feature = (Feature) iterator.next();
268
                        visitor.visit(feature);
269
                }
270
        }
271

    
272
        protected void checkModified() {
273
                if (modified) {
274
                        throw new ConcurrentDataModificationException(store.getName());
275
                }
276
        }
277

    
278
        public boolean isEmpty() throws DataException {
279
                checkModified();
280
                if (this.store.isEditing()) {
281
                        if (this.store.getFeatureManager().hasNews()) {
282
                                return false;
283
                        }
284
                        if (this.provider.isEmpty()) {
285
                                return true;
286
                        }
287
                        return this.provider.getSize()
288
                        + this.store.getFeatureManager().getDeltaSize() == 0;
289
                }
290
                return this.provider.isEmpty();
291
        }
292

    
293
        public Iterator fastIterator() throws DataException {
294
                return this.fastIterator(0);
295
        }
296

    
297
        public Iterator fastIterator(long index) throws DataException {
298
                if (index < 0) {
299
                        throw new IndexOutOfBoundsException("The index (" + index
300
                                        + ") is less than 0");
301
                }
302
                int mode = this.getIteratorMode();
303

    
304
                switch (mode) {
305
                case DEFAULT:
306
                        return new FastDefaultIterator(this, index);
307

    
308
                case FILTERED:
309
                        return new FastFilteredIterator(this, index);
310

    
311

    
312
                case ORDERED:
313
                        return new FastOrderedIterator(this, new FastDefaultIterator(this,
314
                                        0), index);
315

    
316
                case ORDERED_FILTERED:
317
                        return new FastOrderedIterator(this, new FastFilteredIterator(this,
318
                                        0),
319
                                        index);
320

    
321
                case EDITED:
322
                        return new FastEditedIterator(this, index);
323

    
324
                case EDITED_FILTERED:
325
                        return new FastEditedFilteredIterator(this, index);
326

    
327
                case ORDERD_EDITED:
328
                        return new FastOrderedIterator(this,
329
                                        new FastEditedIterator(this, 0), index);
330

    
331
                case ORDERED_EDITED_FILTER:
332
                        return new FastOrderedIterator(this,
333
                                        new FastEditedFilteredIterator(this, 0), index);
334

    
335
                default:
336
                        throw new IllegalArgumentException();
337
                }
338
        }
339

    
340
        public Iterator iterator() throws DataException {
341
                return this.iterator(0);
342
        }
343

    
344
        public Iterator iterator(long index) throws DataException {
345
                if (index < 0) {
346
                        throw new IndexOutOfBoundsException("The index (" + index
347
                                        + ") is less than 0");
348
                }
349
                int mode = this.getIteratorMode();
350

    
351
                switch (mode) {
352
                case DEFAULT:
353
                        return new DefaultIterator(this, index);
354

    
355
                case FILTERED:
356
                        return new FilteredIterator(this, index);
357

    
358
                case ORDERED:
359
                        return new OrderedIterator(this, new DefaultIterator(this, 0),
360
                                        index);
361

    
362
                case ORDERED_FILTERED:
363
                        return new OrderedIterator(this, new FilteredIterator(this, 0),
364
                                        index);
365

    
366
                case EDITED:
367
                        return new EditedIterator(this, index);
368

    
369
                case EDITED_FILTERED:
370
                        return new EditedFilteredIterator(this, index);
371

    
372
                case ORDERD_EDITED:
373
                        return new OrderedIterator(this,
374
                                        new EditedIterator(this, 0), index);
375

    
376
                case ORDERED_EDITED_FILTER:
377
                        return new OrderedIterator(this,
378
                                        new EditedFilteredIterator(this, 0), index);
379

    
380
                default:
381
                        throw new IllegalArgumentException();
382
                }
383

    
384
        }
385

    
386
        private boolean providerCanOrder() {
387
                return this.provider.canOrder();
388
        }
389

    
390
        private boolean providerCanFilter() {
391
                return this.provider.canFilter();
392
        }
393

    
394
        private int getIteratorMode() {
395

    
396
                if (this.iteratorMode != NO_CHECKED) {
397
                        return this.iteratorMode;
398
                }
399

    
400
                // TODO Tener en cuenta las transformaciones ???
401

    
402
                if (store.isEditing() && store.getFeatureManager().hasChanges()) {
403
                        if (this.query.hasOrder()) { // En edicion siempre ordeno yo.
404
                                if (this.query.hasFilter()) {
405
                                        return ORDERED_EDITED_FILTER;
406
                                } else {
407
                                        return ORDERD_EDITED;
408
                                }
409
                        } else {
410
                                if (this.query.hasFilter()) {
411
                                        return EDITED_FILTERED;
412
                                } else {
413
                                        return EDITED;
414
                                }
415
                        }
416
                } else {
417
                        boolean useMyFilter = this.query.hasFilter();
418
                        boolean useMyOrder = this.query.hasOrder();
419
                        if (this.providerCanOrder() && this.transform.isEmpty()) {
420
                                useMyOrder = false;
421
                        }
422
                        if (this.providerCanFilter() && this.transform.isEmpty()) {
423
                                useMyFilter = false;
424
                        }
425

    
426
                        if (useMyOrder) {
427
                                if (useMyFilter) {
428
                                        return ORDERED_FILTERED;// ORDERED_FILTERED;
429
                                } else {
430
                                        return ORDERED;// ORDERED;
431
                                }
432
                        } else {
433
                                if (useMyFilter) {
434
                                        return FILTERED;// FILTERED;
435
                                } else {
436
                                        return DEFAULT;// DEFAULT;
437
                                }
438
                        }
439
                }
440

    
441
        }
442

    
443
        public void delete(Feature feature) throws DataException {
444
                this.featureToIgnoreNotification = feature;
445
                this.store.delete(feature);
446
                if (this.size > 0) {
447
                        this.size--;
448
                }
449
                this.featureToIgnoreNotification = null;
450
        }
451

    
452
        public void insert(EditableFeature feature) throws DataException {
453
                this.featureToIgnoreNotification = feature;
454
                this.store.insert(feature);
455
                if (this.size >= 0) {
456
                        this.size++;
457
                }
458
                this.featureToIgnoreNotification = null;
459
        }
460

    
461
        public void update(EditableFeature feature) throws DataException {
462
                this.featureToIgnoreNotification = feature;
463
                this.store.update(feature);
464
                this.featureToIgnoreNotification = null;
465
        }
466

    
467
}