Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / impl / featureset / DefaultFeatureSet.java @ 26252

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

    
26
public class DefaultFeatureSet implements FeatureSet, Observer {
27

    
28

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

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

    
52

    
53
        public DefaultFeatureSet(DefaultFeatureStore store, FeatureQuery query)
54
        throws DataException {
55
                this.featureToIgnoreNotification = null;
56
                this.iteratorMode = NO_CHECKED;
57
                this.modified = false;
58
                this.size = -1;
59
                this.orderedData = null;
60
                this.store = store;
61
                if (this.store.isEditing()) {
62
                        this.transform = this.store.getFeatureTypeManager().getTransforms();
63
                } else {
64
                        this.transform = (DefaultFeatureStoreTransforms) store
65
                                .getTransforms();
66
                }
67
                this.query = query;
68
                this.queryForProvider = query.getCopy();
69
                this.featureTypes = new ArrayList();
70
                this.featureTypes.add(this.query.getFeatureType());
71
                if (!this.transform.isEmpty()) {
72
                        this.queryForProvider.setAttributeNames(null);
73
                        this.queryForProvider.setFeatureType(this.transform
74
                                        .getSourceFeatureTypeFrom(this.query.getFeatureType()));
75
                        this.queryForProvider.setFilter(null);
76
                        // TODO Habria que comprobar si todos los campos que usan el filtro
77
                        // son del provider. Si esto se cumple, no eliminamos el filtro.
78
                }
79

    
80
                if (query.hasFilter() && store.getIndexes() != null) {
81
                        this.provider = (FeatureSetProvider) store.getIndexes()
82
                        .getFeatureSet(this.queryForProvider.getFilter());
83
                }
84
                if (this.provider == null) {
85
                        this.provider = this.store.getProvider().createSet(
86
                                        this.queryForProvider);
87
                }
88
                this.store.addObserver(this);
89
        }
90

    
91
        public FeatureType getDefaultFeatureType() {
92
                return this.query.getFeatureType();
93
        }
94

    
95
        public List getFeatureTypes() {
96
                return Collections.unmodifiableList(this.featureTypes);
97
        }
98

    
99
        public long getSize() throws DataException {
100
                this.checkModified();
101
                if (size < 0) {
102
                        size = calculateSize();
103
                }
104
                return size;
105
        }
106

    
107
        private long calculateSize() throws DataException {
108
                int mode = this.getIteratorMode();
109
                if ((mode & FILTERED) == FILTERED) {
110
                        long mySize =0;
111
                        Iterator iter = this.fastIterator();
112
                        try{
113
                                while (true) {
114
                                        iter.next();
115
                                        mySize++;
116
                                }
117
                        } catch (NoSuchElementException e){
118
                                return mySize;
119
                        }
120
                } else if ((mode & EDITED) == EDITED) {
121
                        return provider.getSize()
122
                        + store.getFeatureManager().getDeltaSize();
123
                }
124
                return provider.getSize();
125
        }
126

    
127
        public void dispose() {
128
                this.store.deleteObserver(this);
129
                this.provider = null;
130

    
131
                this.featureToIgnoreNotification = null;
132
                this.orderedData = null;
133
                this.store = null;
134
                this.transform = null;
135
                this.query = null;
136
                this.queryForProvider = null;
137
                this.featureTypes = null;
138

    
139
        }
140

    
141
        public boolean isFromStore(DataStore store) {
142
                return this.store.equals(store);
143
        }
144

    
145
        public void update(Observable obsevable, Object notification) {
146
                if (modified) {
147
                        return;
148
                }
149

    
150
                String type = ((FeatureStoreNotification) notification).getType();
151

    
152
                if (
153
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_INSERT)
154
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DELETE)
155
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE)
156
                ) {
157
                        if( this.featureToIgnoreNotification == ((FeatureStoreNotification) notification).getFeature() ) {
158
                                return;
159
                        }
160
                        modified = true;
161
                        return;
162
                }
163
                if (
164
                                type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UPDATE_TYPE)
165
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REDO)
166
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_UNDO)
167
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CANCELEDITING)
168
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_REFRESH)
169
                                || type.equalsIgnoreCase(FeatureStoreNotification.COMPLEX_NOTIFICATION)
170
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_CLOSE)
171
                                || type.equalsIgnoreCase(FeatureStoreNotification.AFTER_DISPOSE)
172
                                || type.equalsIgnoreCase(FeatureStoreNotification.RESOURCE_CHANGED)
173
                                || type.equalsIgnoreCase(FeatureStoreNotification.TRANSFORM_CHANGE)
174
                ) {
175
                        modified = true;
176
                        return;
177
                }
178
        }
179

    
180
        public void accept(Visitor visitor) throws BaseException {
181
                Iterator iterator = iterator();
182

    
183
                while (iterator.hasNext()) {
184
                        Feature feature = (Feature) iterator.next();
185
                        visitor.visit(feature);
186
                }
187
        }
188

    
189
        protected void checkModified() {
190
                if (modified) {
191
                        throw new ConcurrentDataModificationException(store.getName());
192
                }
193
        }
194

    
195
        public boolean isEmpty() throws DataException {
196
                checkModified();
197
                if (this.store.isEditing()) {
198
                        if (this.store.getFeatureManager().hasNews()) {
199
                                return false;
200
                        }
201
                        if (this.provider.isEmpty()) {
202
                                return true;
203
                        }
204
                        return this.provider.getSize()
205
                        + this.store.getFeatureManager().getDeltaSize() == 0;
206
                }
207
                return this.provider.isEmpty();
208
        }
209

    
210
        public Iterator fastIterator() throws DataException {
211
                return this.fastIterator(0);
212
        }
213

    
214
        public Iterator fastIterator(long index) throws DataException {
215
                if (index < 0) {
216
                        throw new IndexOutOfBoundsException("The index (" + index
217
                                        + ") is less than 0");
218
                }
219
                int mode = this.getIteratorMode();
220

    
221
                switch (mode) {
222
                case DEFAULT:
223
                        return new FastDefaultIterator(this, index);
224

    
225
                case FILTERED:
226
                        return new FastFilteredIterator(this, index);
227

    
228

    
229
                case ORDERED:
230
                        return new FastOrderedIterator(this, new FastDefaultIterator(this,
231
                                        0), index);
232

    
233
                case ORDERED_FILTERED:
234
                        return new FastOrderedIterator(this, new FastFilteredIterator(this,
235
                                        0),
236
                                        index);
237

    
238
                case EDITED:
239
                        return new FastEditedIterator(this, index);
240

    
241
                case EDITED_FILTERED:
242
                        return new FastEditedFilteredIterator(this, index);
243

    
244
                case ORDERD_EDITED:
245
                        return new FastOrderedIterator(this,
246
                                        new FastEditedIterator(this, 0), index);
247

    
248
                case ORDERED_EDITED_FILTER:
249
                        return new FastOrderedIterator(this,
250
                                        new FastEditedFilteredIterator(this, 0), index);
251

    
252
                default:
253
                        throw new IllegalArgumentException();
254
                }
255
        }
256

    
257
        public Iterator iterator() throws DataException {
258
                return this.iterator(0);
259
        }
260

    
261
        public Iterator iterator(long index) throws DataException {
262
                if (index < 0) {
263
                        throw new IndexOutOfBoundsException("The index (" + index
264
                                        + ") is less than 0");
265
                }
266
                int mode = this.getIteratorMode();
267

    
268
                switch (mode) {
269
                case DEFAULT:
270
                        return new DefaultIterator(this, index);
271

    
272
                case FILTERED:
273
                        return new FilteredIterator(this, index);
274

    
275
                case ORDERED:
276
                        return new OrderedIterator(this, new DefaultIterator(this, 0),
277
                                        index);
278

    
279
                case ORDERED_FILTERED:
280
                        return new OrderedIterator(this, new FilteredIterator(this, 0),
281
                                        index);
282

    
283
                case EDITED:
284
                        return new EditedIterator(this, index);
285

    
286
                case EDITED_FILTERED:
287
                        return new EditedFilteredIterator(this, index);
288

    
289
                case ORDERD_EDITED:
290
                        return new OrderedIterator(this,
291
                                        new EditedIterator(this, 0), index);
292

    
293
                case ORDERED_EDITED_FILTER:
294
                        return new OrderedIterator(this,
295
                                        new EditedFilteredIterator(this, 0), index);
296

    
297
                default:
298
                        throw new IllegalArgumentException();
299
                }
300

    
301
        }
302

    
303
        private boolean providerCanOrder() {
304
                return this.provider.canOrder();
305
        }
306

    
307
        private boolean providerCanFilter() {
308
                return this.provider.canFilter();
309
        }
310

    
311
        private int getIteratorMode() {
312

    
313
                if (this.iteratorMode != NO_CHECKED) {
314
                        return this.iteratorMode;
315
                }
316

    
317
                // TODO Tener en cuenta las transformaciones ???
318

    
319
                if (store.isEditing() && store.getFeatureManager().hasChanges()) {
320
                        if (this.query.hasOrder()) { // En edicion siempre ordeno yo.
321
                                if (this.query.hasFilter()) {
322
                                        return ORDERED_EDITED_FILTER;
323
                                } else {
324
                                        return ORDERD_EDITED;
325
                                }
326
                        } else {
327
                                if (this.query.hasFilter()) {
328
                                        return EDITED_FILTERED;
329
                                } else {
330
                                        return EDITED;
331
                                }
332
                        }
333
                } else {
334
                        boolean useMyFilter = this.query.hasFilter();
335
                        boolean useMyOrder = this.query.hasOrder();
336
                        if (this.providerCanOrder() && this.transform.isEmpty()) {
337
                                useMyOrder = false;
338
                        }
339
                        if (this.providerCanFilter() && this.transform.isEmpty()) {
340
                                useMyFilter = false;
341
                        }
342

    
343
                        if (useMyOrder) {
344
                                if (useMyFilter) {
345
                                        return ORDERED_FILTERED;// ORDERED_FILTERED;
346
                                } else {
347
                                        return ORDERED;// ORDERED;
348
                                }
349
                        } else {
350
                                if (useMyFilter) {
351
                                        return FILTERED;// FILTERED;
352
                                } else {
353
                                        return DEFAULT;// DEFAULT;
354
                                }
355
                        }
356
                }
357

    
358
        }
359

    
360
        public void delete(Feature feature) throws DataException {
361
                this.featureToIgnoreNotification = feature;
362
                this.store.delete(feature);
363
                if (this.size > 0) {
364
                        this.size--;
365
                }
366
                this.featureToIgnoreNotification = null;
367
        }
368

    
369
        public void insert(EditableFeature feature) throws DataException {
370
                this.featureToIgnoreNotification = feature;
371
                this.store.insert(feature);
372
                if (this.size >= 0) {
373
                        this.size++;
374
                }
375
                this.featureToIgnoreNotification = null;
376
        }
377

    
378
        public void update(EditableFeature feature) throws DataException {
379
                this.featureToIgnoreNotification = feature;
380
                this.store.update(feature);
381
                this.featureToIgnoreNotification = null;
382
        }
383

    
384
}