Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / fmap / dal / feature / paging / impl / FeaturePagingHelperImpl.java @ 44488

History | View | Annotate | Download (33.4 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8 40559 jjdelcerro
 * as published by the Free Software Foundation; either version 3
9 40435 jjdelcerro
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21 40559 jjdelcerro
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23 40435 jjdelcerro
 */
24
package org.gvsig.fmap.dal.feature.paging.impl;
25
26 43660 jjdelcerro
import java.util.ArrayList;
27 41212 jjdelcerro
import java.util.Collection;
28 43660 jjdelcerro
import java.util.Date;
29 41212 jjdelcerro
import java.util.Iterator;
30
import java.util.List;
31
import java.util.ListIterator;
32 44253 jjdelcerro
import java.util.logging.Level;
33 40435 jjdelcerro
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.feature.EditableFeature;
38
import org.gvsig.fmap.dal.feature.Feature;
39
import org.gvsig.fmap.dal.feature.FeatureQuery;
40
import org.gvsig.fmap.dal.feature.FeatureSelection;
41
import org.gvsig.fmap.dal.feature.FeatureSet;
42
import org.gvsig.fmap.dal.feature.FeatureStore;
43
import org.gvsig.fmap.dal.feature.FeatureType;
44 41819 fdiaz
import org.gvsig.fmap.dal.feature.exception.ConcurrentDataModificationException;
45 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
46 42775 jjdelcerro
import org.gvsig.fmap.dal.feature.impl.dynobjectutils.DynObjectFeatureFacade;
47
import org.gvsig.fmap.dal.feature.paging.FacadeOfAFeaturePagingHelper;
48 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.paging.FeaturePagingHelper;
49
import org.gvsig.tools.dynobject.DynObject;
50
import org.gvsig.tools.dynobject.DynObjectSet;
51
import org.gvsig.tools.dynobject.impl.DefaultDynObjectPagingHelper;
52
import org.gvsig.tools.exception.BaseException;
53 44253 jjdelcerro
import org.gvsig.tools.util.UnmodifiableBasicList;
54
import org.gvsig.tools.util.UnmodifiableBasicList64;
55 40435 jjdelcerro
import org.gvsig.tools.visitor.VisitCanceledException;
56
import org.gvsig.tools.visitor.Visitor;
57
58
/**
59
 * Helper class to access the values of a FeatureCollection by position. Handles
60
 * pagination automatically to avoid filling the memory in case of big
61
 * collections.
62 41819 fdiaz
 *
63 40435 jjdelcerro
 * TODO: evaluate if its more convenient to read values in the background when
64
 * the returned value is near the end of the page, instead of loading a page on
65
 * demand.
66 41819 fdiaz
 *
67 40435 jjdelcerro
 * @author gvSIG Team
68
 */
69
public class FeaturePagingHelperImpl extends DefaultDynObjectPagingHelper
70
    implements FeaturePagingHelper {
71
72 43660 jjdelcerro
    private static final Logger LOG = LoggerFactory.getLogger(FeaturePagingHelperImpl.class);
73 40435 jjdelcerro
74 43660 jjdelcerro
    private static class Page {
75
76 43691 jjdelcerro
        private Feature[] features;
77 43660 jjdelcerro
        private final long number;
78
        private final int size;
79
        private long lastaccess;
80
81
        public Page(long number, int size) {
82
            this.size = size;
83
            this.number = number;
84
            this.features = new Feature[size];
85
            this.lastaccess = 0;
86
        }
87
88
        public void setFeature(int i, Feature copy) {
89
            this.features[i] = copy;
90
        }
91
92
        public Feature[] getFeatures() {
93
            this.lastaccess = (new Date()).getTime();
94
            return this.features;
95
        }
96
97
        public long getPageNumber() {
98
            return this.number;
99
        }
100
101
        public long getLastAccess() {
102
            return this.lastaccess;
103
        }
104
105
        public int size() {
106
            return this.size;
107
        }
108 43691 jjdelcerro
109
        public void dispose() {
110
            for (int i = 0; i < features.length; i++) {
111
                features[i] = null;
112
            }
113
            this.features = null;
114
            this.lastaccess = 0;
115
        }
116 43660 jjdelcerro
    }
117
118
    private static class PageCache {
119
120
        private final int maxpages;
121 43691 jjdelcerro
        private List<Page> pages;
122 43660 jjdelcerro
123
        public PageCache(int maxpages) {
124
            this.maxpages = maxpages;
125
            this.pages = new ArrayList<>();
126
        }
127
128 43691 jjdelcerro
        public void clear() {
129
            for (Page page : pages) {
130
                page.dispose();
131
            }
132
            this.pages = new ArrayList<>();
133
        }
134
135 43660 jjdelcerro
        public Page get(long pageNumber) {
136
            for( Page page : pages ) {
137
                if( page.getPageNumber() == pageNumber ) {
138
                    return page;
139
                }
140
            }
141
            return null;
142
        }
143
144
        public void add(Page page) {
145
            if( this.pages.size()< this.maxpages ) {
146
                this.pages.add(page);
147
                return;
148
            }
149
            int toDrop = 0;
150
            for( int i=0; i<this.pages.size(); i++ ) {
151
                if( this.pages.get(i).getLastAccess()<this.pages.get(toDrop).getLastAccess() ) {
152
                    toDrop = i;
153
                }
154
            }
155
            this.pages.set(toDrop, page);
156
        }
157
    }
158
159 40435 jjdelcerro
    private FeatureQuery query;
160
161
    private FeatureStore featureStore;
162
163
    /** If the selected Features must be returned as the first ones. **/
164
    private boolean selectionUp = false;
165
166
    private FeatureSet featSet = null;
167
    private FeatureSelection initialSelection = null;
168
169
    private Feature[] features = null;
170 43660 jjdelcerro
    private PageCache cachedPages = null;
171 40435 jjdelcerro
172 41212 jjdelcerro
    private boolean initialization_completed = false;
173 42807 jjdelcerro
174
    private FeatureSelection selection = null;
175 40435 jjdelcerro
    /**
176
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
177 41819 fdiaz
     *
178 40435 jjdelcerro
     * @param featureStore
179
     *            to extract data from
180
     * @throws DataException
181
     *             if there is an error initializing the helper
182
     */
183
    public FeaturePagingHelperImpl(FeatureStore featureStore)
184
        throws BaseException {
185
        this(featureStore, DEFAULT_PAGE_SIZE);
186
    }
187
188
    /**
189
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
190 41819 fdiaz
     *
191 40435 jjdelcerro
     * @param featureStore
192
     *            to extract data from
193
     * @param pageSize
194
     *            the number of elements per page data
195
     * @throws DataException
196
     *             if there is an error initializing the helper
197
     */
198
    public FeaturePagingHelperImpl(FeatureStore featureStore, int pageSize)
199
        throws BaseException {
200
        this(featureStore, null, pageSize);
201
    }
202
203
    /**
204
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
205 41819 fdiaz
     *
206 40435 jjdelcerro
     * @param featureStore
207
     *            to extract data from
208
     * @throws DataException
209
     *             if there is an error initializing the helper
210
     */
211
    public FeaturePagingHelperImpl(FeatureStore featureStore,
212
        FeatureQuery featureQuery) throws BaseException {
213
        this(featureStore, featureQuery, DEFAULT_PAGE_SIZE);
214
    }
215
216
    /**
217
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
218 41819 fdiaz
     *
219 40435 jjdelcerro
     * @param featureSet
220
     *            to extract data from
221
     * @param pageSize
222
     *            the number of elements per page data
223
     * @throws DataException
224
     *             if there is an error initializing the helper
225
     */
226
    public FeaturePagingHelperImpl(FeatureStore featureStore,
227
        FeatureQuery featureQuery, int pageSize) throws BaseException {
228
        super();
229 43660 jjdelcerro
        this.cachedPages = new PageCache(3);
230 40435 jjdelcerro
        FeatureQuery query = featureQuery;
231
        if (featureQuery == null) {
232
            query = featureStore.createFeatureQuery();
233
            query.setFeatureType(featureStore.getDefaultFeatureType());
234
        }
235
236
        this.featureStore = featureStore;
237
        this.query = query;
238
        this.query.setPageSize(pageSize);
239
240
        setDefaultCalculator(new Sizeable() {
241
            public long getSize() {
242
                    FeatureSet featureSet = getFeatureSet(false);
243
                try {
244
                                        return featureSet.getSize();
245
                } catch (BaseException e) {
246
                    LOG.error("Error getting the size of the FeatureSet: "
247
                        + featureSet, e);
248
                    return 0l;
249
                }
250
            }
251
        }, pageSize);
252 41819 fdiaz
253
254 40595 jldominguez
        if (LOG.isDebugEnabled()) {
255 41819 fdiaz
256 40595 jldominguez
            LOG.debug("FeaturePagingHelperImpl created with {} pages, "
257
                + "and a page size of {}", new Long(getCalculator()
258
                .getNumPages()), new Integer(pageSize));
259
        }
260 41212 jjdelcerro
        this.initialization_completed = true;
261 40435 jjdelcerro
    }
262
263
    /**
264
     * @return the selectionUp status
265
     */
266 41630 jjdelcerro
    public boolean isSelectionUp() {
267 40435 jjdelcerro
        return selectionUp;
268
    }
269 42807 jjdelcerro
270
    public FeatureSelection getSelection() {
271
        if (selection == null) {
272
            try {
273
                return getFeatureStore().getFeatureSelection();
274
            } catch (Exception e) {
275
                LOG.warn("Error getting the selection", e);
276
            }
277
        }
278
        return selection;
279
    }
280
281
    public void setSelection(FeatureSelection selection) {
282
        this.selection = selection;
283
    }
284
285
    @Override
286 40435 jjdelcerro
    public void setSelectionUp(boolean selectionUp) {
287
        this.selectionUp = selectionUp;
288
        try {
289 43728 jjdelcerro
            this.cachedPages.clear();
290 42807 jjdelcerro
            FeatureSelection currentSelection = getSelection();
291 41630 jjdelcerro
            if (selectionUp && !currentSelection.isEmpty()) {
292
                initialSelection =(FeatureSelection) currentSelection.clone();
293 40435 jjdelcerro
                setCalculator(new OneSubsetOneSetPagingCalculator(
294
                    new FeatureSetSizeableDelegate(initialSelection),
295
                    new FeatureSetSizeableDelegate(getFeatureSet(false)),
296
                    getMaxPageSize()));
297
            } else {
298
                if (initialSelection != null) {
299
                    initialSelection.dispose();
300
                    initialSelection = null;
301
                }
302
                setDefaultCalculator(new FeatureSetSizeableDelegate(
303
                    getFeatureSet(false)), getMaxPageSize());
304
            }
305
        } catch (BaseException e) {
306
            LOG.error("Error setting the selection up setting to: "
307
                + selectionUp, e);
308
        } catch (CloneNotSupportedException e) {
309
            LOG.error("Error cloning the selection "
310
                + "while setting the selection up", e);
311
        }
312
    }
313
314 42991 jbadia
    public synchronized Feature getFeatureAt(long index) throws BaseException {
315 40435 jjdelcerro
        // Check if we have currently loaded the viewed page data,
316
        // or we need to load a new one
317 42991 jbadia
            int maxPageSize = getMaxPageSize();
318
            long currentPage = getCurrentPage();
319
            long currentPage2 = currentPage;
320
321
322
        long pageForIndex = (long) Math.floor(index / maxPageSize);
323 40435 jjdelcerro
324 42991 jbadia
        if (pageForIndex != currentPage) {
325 40435 jjdelcerro
            setCurrentPage(pageForIndex);
326 42991 jbadia
            currentPage2 = getCurrentPage();
327 40435 jjdelcerro
        }
328
329 42991 jbadia
        long positionForIndex = index - (currentPage2 * maxPageSize);
330 40435 jjdelcerro
331 41268 jjdelcerro
        if (positionForIndex >= getCurrentPageFeatures().length) {
332 40435 jjdelcerro
            throw new FeatureIndexException(
333
                new IndexOutOfBoundsException("positionForIndex too big: "
334
                    + positionForIndex));
335
        } else {
336 41268 jjdelcerro
            Feature feature = getCurrentPageFeatures()[(int) positionForIndex];
337 41212 jjdelcerro
            return feature;
338 40435 jjdelcerro
        }
339 41819 fdiaz
340 40435 jjdelcerro
    }
341
342
    public Feature[] getCurrentPageFeatures() {
343 41268 jjdelcerro
        if( this.features==null ) {
344
            try {
345
                this.loadCurrentPageData();
346
            } catch (BaseException ex) {
347
                // Do nothing
348
            }
349
            if( this.features == null ) {
350
                String msg = "Can't retrieve the features from current page.";
351
                LOG.warn(msg);
352
                throw new RuntimeException(msg);
353
            }
354
        }
355 40435 jjdelcerro
        return features;
356
    }
357
358
    /**
359
     * Gets the feature set.
360
     * The boolean tells whether we must create the featureset
361
     * again (for example perhaps we need it after a feature
362
     * has been added/removed)
363
     */
364
    private FeatureSet getFeatureSet(boolean reset) {
365 41819 fdiaz
366 40435 jjdelcerro
        if (featSet == null || reset) {
367 41819 fdiaz
368 40435 jjdelcerro
            if (featSet != null) {
369
                try {
370
                    featSet.dispose();
371
                } catch (Exception ex) {
372
                    LOG.info("Error while disposing featset.", ex);
373
                }
374
            }
375 41819 fdiaz
376 40435 jjdelcerro
            try {
377 41819 fdiaz
                FeatureStore featureStore = getFeatureStore();
378 40435 jjdelcerro
                synchronized (featureStore) {
379 41819 fdiaz
                    featSet = featureStore.getFeatureSet(getFeatureQuery());
380 40435 jjdelcerro
                }
381
            } catch (DataException e) {
382
                throw new RuntimeException("Error getting a feature set with the query " + getFeatureQuery());
383
            }
384
        }
385
        return featSet;
386
    }
387 41819 fdiaz
388 43691 jjdelcerro
    @Override
389 40435 jjdelcerro
    public DynObjectSet getDynObjectSet() {
390
            return getFeatureSet(false).getDynObjectSet();
391
    }
392
393 43691 jjdelcerro
    @Override
394 40435 jjdelcerro
    public void reloadCurrentPage() throws BaseException {
395 41819 fdiaz
396 40435 jjdelcerro
        boolean sel_up = this.isSelectionUp();
397
398
        setSelectionUp(false);
399
        if (getCalculator().getCurrentPage() > -1) {
400 43691 jjdelcerro
            this.cachedPages.clear();
401 40435 jjdelcerro
            loadCurrentPageData();
402
        }
403 41819 fdiaz
404 40435 jjdelcerro
        if (sel_up) {
405
            setSelectionUp(true);
406
        }
407
    }
408
409 43691 jjdelcerro
    @Override
410 40435 jjdelcerro
    public void reload() throws BaseException {
411 41819 fdiaz
412 43726 jjdelcerro
        this.cachedPages.clear();
413 40435 jjdelcerro
        /*
414
         * Force re-creation of feature set
415
         */
416
        this.getFeatureSet(true);
417
418 41819 fdiaz
419 40435 jjdelcerro
        setDefaultCalculator(new Sizeable() {
420
            public long getSize() {
421
                    FeatureSet featureSet = getFeatureSet(false);
422
                try {
423
                                        return featureSet.getSize();
424
                } catch (BaseException e) {
425
                    LOG.error("Error getting the size of the FeatureSet: "
426
                        + featureSet, e);
427
                    return 0l;
428
                }
429
            }
430
        }, getCalculator().getMaxPageSize());
431
        reloadCurrentPage();
432
    }
433
434
    public FeatureStore getFeatureStore() {
435
        return featureStore;
436
    }
437
438
    public FeatureQuery getFeatureQuery() {
439
        return query;
440
    }
441
442
    /**
443
     * Loads all the Features of the current page.
444 43660 jjdelcerro
     * @throws org.gvsig.tools.exception.BaseException
445 40435 jjdelcerro
     */
446 43660 jjdelcerro
    @Override
447 42991 jbadia
    protected synchronized void loadCurrentPageData() throws BaseException {
448 41212 jjdelcerro
        if( !initialization_completed ) {
449
            return;
450
        }
451 40435 jjdelcerro
        final int currentPageSize = getCalculator().getCurrentPageSize();
452 43660 jjdelcerro
        final long currentPage = getCalculator().getCurrentPage();
453
        Page page = this.cachedPages.get(currentPage);
454
        if( page==null ) {
455
            page = new Page(currentPage, currentPageSize);
456 40435 jjdelcerro
457 43660 jjdelcerro
            long t1 = 0;
458
            if (LOG.isTraceEnabled()) {
459
                t1 = System.currentTimeMillis();
460
            }
461 40435 jjdelcerro
462 43660 jjdelcerro
            if (selectionUp) {
463
                loadCurrentPageDataWithSelectionUp(page);
464
            } else {
465
                loadCurrentPageDataNoSelection(page);
466
            }
467 40435 jjdelcerro
468 43660 jjdelcerro
            if (LOG.isTraceEnabled()) {
469
                long t2 = System.currentTimeMillis();
470
                LOG.trace("Time to load {} features: {} ms", currentPageSize, t2 - t1);
471
            }
472
            this.cachedPages.add(page);
473 40435 jjdelcerro
        }
474 43660 jjdelcerro
        this.features = page.getFeatures();
475 40435 jjdelcerro
    }
476 41819 fdiaz
477 43660 jjdelcerro
    private void loadCurrentPageDataWithSelectionUp(final Page page)
478 41630 jjdelcerro
            throws BaseException {
479 40435 jjdelcerro
        FeatureSelection selection = initialSelection;
480 41630 jjdelcerro
        if (selection == null) {
481 43660 jjdelcerro
            loadCurrentPageDataNoSelection(page);
482 41630 jjdelcerro
        } else {
483
            FeatureSet set = getFeatureSet(false);
484
            try {
485
                OneSubsetOneSetPagingCalculator twoSetsCalculator = null;
486
                if (getCalculator() instanceof OneSubsetOneSetPagingCalculator) {
487
                    twoSetsCalculator
488
                            = (OneSubsetOneSetPagingCalculator) getCalculator();
489
                } else {
490
                    twoSetsCalculator
491
                            = new OneSubsetOneSetPagingCalculator(
492
                                    new FeatureSetSizeableDelegate(selection),
493
                                    new FeatureSetSizeableDelegate(set),
494
                                    getMaxPageSize(), getCalculator().getCurrentPage());
495
                    setCalculator(twoSetsCalculator);
496
                }
497 40435 jjdelcerro
498
                // First load values from the selection, if the current page has
499 41630 jjdelcerro
                // elements from it
500
                if (twoSetsCalculator.hasCurrentPageAnyValuesInFirstSet()) {
501 43660 jjdelcerro
                    loadDataFromFeatureSet(page, 0, selection,
502 41630 jjdelcerro
                            twoSetsCalculator.getFirstSetInitialIndex(),
503
                            twoSetsCalculator.getFirstSetHowMany(), null);
504
                }
505 40435 jjdelcerro
                // Next, load values from the FeatureSet if the current page has values
506 41630 jjdelcerro
                // from it
507
                if (twoSetsCalculator.hasCurrentPageAnyValuesInSecondSet()) {
508
                    loadDataFromFeatureSet(
509 43660 jjdelcerro
                            page,
510 41630 jjdelcerro
                            // The cast will work as that size will be <= maxpagesize,
511
                            // which is an int
512
                            (int) twoSetsCalculator.getFirstSetHowMany(), set,
513
                            twoSetsCalculator.getSecondSetInitialIndex(),
514
                            twoSetsCalculator.getSecondSetHowMany(), selection);
515
                }
516
            } finally {
517
                /*
518
                 * This is the feature set
519
                 * we dont want to lose it
520
                 */
521
                // set.dispose();
522
            }
523 40435 jjdelcerro
        }
524
    }
525
526 43660 jjdelcerro
    private void loadCurrentPageDataNoSelection(final Page page)
527 40435 jjdelcerro
        throws BaseException {
528
529
        long firstPosition = getCalculator().getInitialIndex();
530
531
        if (LOG.isDebugEnabled()) {
532 43660 jjdelcerro
            LOG.debug("Loading {} Features starting at position {}",
533
                getCalculator().getCurrentPageSize(), firstPosition
534
            );
535 40435 jjdelcerro
        }
536
537
        FeatureSet featureSet = getFeatureSet(false);
538
        try {
539 43660 jjdelcerro
                loadDataFromFeatureSet(page, 0, featureSet, firstPosition,
540 40435 jjdelcerro
                                getCalculator().getCurrentPageSize(), null);
541
        } catch(DataException ex) {
542
            throw ex;
543
            // } finally {
544
                // featureSet.dispose();
545
        }
546 41819 fdiaz
547 40435 jjdelcerro
    }
548
549 43660 jjdelcerro
    private void loadDataFromFeatureSet(final Page page,
550 40435 jjdelcerro
        final int valuesPosition, FeatureSet set, long initialIndex,
551
        final long howMany, final FeatureSelection selectedFeaturesToSkip)
552
        throws DataException {
553
554
        try {
555
            set.accept(new Visitor() {
556
                private int i = valuesPosition;
557
558 43660 jjdelcerro
                @Override
559 40435 jjdelcerro
                public void visit(Object obj) throws VisitCanceledException,
560
                    BaseException {
561
                    if (i >= valuesPosition + howMany) {
562
                        throw new VisitCanceledException();
563
                    }
564
                    Feature current = (Feature) obj;
565
                    // Add the current Feature only if we don't skip selected
566
                    // features or the feature is not selected
567
                    if (selectedFeaturesToSkip == null
568
                        || !selectedFeaturesToSkip.isSelected(current)) {
569 41630 jjdelcerro
                        try {
570 43660 jjdelcerro
                            page.setFeature(i,current.getCopy());
571 41630 jjdelcerro
                            i++;
572
                        } catch(Exception ex) {
573
                            // Aqui no deberia petar, pero...
574
                            // me he encontrado un caso que tenia una referencia a
575 41819 fdiaz
                            // una feature seleccionada que ya no existia. No se como
576 41630 jjdelcerro
                            // habia pasado, se habia quedado de antes guardada en el
577
                            // proyecto pero la feature ya no existia, y eso hacia que
578
                            // petase al intentar leer de disco la feature a partir
579
                            // de una referencia no valida.
580
                        }
581 40435 jjdelcerro
                    }
582
                }
583 43358 jjdelcerro
            }, initialIndex, howMany);
584
        } catch(VisitCanceledException ex) {
585
            // Do nothing
586 40435 jjdelcerro
        } catch (BaseException e) {
587
            if (e instanceof DataException) {
588
                throw ((DataException) e);
589
            } else {
590
                LOG.error("Error loading the data starting at position {}",
591
                    new Long(initialIndex), e);
592
            }
593
        }
594
    }
595
596
    public void delete(Feature feature) throws BaseException {
597
        featureStore.delete(feature);
598
        /*
599
         * Force re-creation of feature set
600
         */
601
        this.getFeatureSet(true);
602
603
        reloadCurrentPage();
604
    }
605
606
    public void insert(EditableFeature feature) throws BaseException {
607
            featureStore.insert(feature);
608
        /*
609
         * Force re-creation of feature set
610
         */
611
        this.getFeatureSet(true);
612
613
        reloadCurrentPage();
614
    }
615 44488 jjdelcerro
616
    public boolean isEmpty() {
617
        try {
618
            return getFeatureSet(false).isEmpty();
619
        } catch (ConcurrentDataModificationException ex) {
620
            LOG.warn("ConcurrentDataModification error asking about the emptiness of the list. Retrying reloading data.");
621
            try {
622
                reload();
623
            } catch (BaseException e) {
624
                LOG.warn("Error reloading data.", e);
625
                throw new RuntimeException(e);
626
            }
627
            try {
628
                return getFeatureSet(false).isEmpty();
629
            } catch (DataException e) {
630
                LOG.warn("Error asking about the emptiness of the list after reloading data.",e);
631
                throw new RuntimeException(e);
632
            }
633
        } catch (DataException ex) {
634
            throw  new RuntimeException(ex);
635
        }
636
    }
637 40435 jjdelcerro
638
    public void update(EditableFeature feature) throws BaseException {
639
            featureStore.update(feature);
640
        /*
641
         * Force re-creation of feature set
642
         */
643
        this.getFeatureSet(true);
644
645
        reloadCurrentPage();
646
    }
647
648
    public FeatureType getFeatureType() {
649 41819 fdiaz
650 40435 jjdelcerro
        FeatureType ft = null;
651 41819 fdiaz
652 40435 jjdelcerro
        try {
653
            ft = featureStore.getDefaultFeatureType();
654
        } catch (DataException e) {
655
            LOG.error("Error while getting feature type: " +
656
                e.getMessage(), e);
657
        }
658
        return ft;
659 41819 fdiaz
660 40435 jjdelcerro
        /*
661 41819 fdiaz
         *
662 40435 jjdelcerro
        FeatureSet featureSet = getFeatureSet();
663
        try {
664
            return featureSet.getDefaultFeatureType();
665
        } finally {
666
            featureSet.dispose();
667
        }
668
        */
669
670 41819 fdiaz
671 40435 jjdelcerro
    }
672
673
    protected void doDispose() throws BaseException {
674
        initialSelection.dispose();
675
        if (featSet != null) {
676
            try {
677
                featSet.dispose();
678
            } catch (Exception ex) {
679
                LOG.info("Error while disposing featset.", ex);
680
            }
681
        }
682
    }
683
684
    public DynObject[] getCurrentPageDynObjects() {
685
        Feature[] features = getCurrentPageFeatures();
686
        DynObject[] dynobjects = new DynObject[features.length];
687
        for (int i = 0; i < dynobjects.length; i++) {
688
            dynobjects[i] = new DynObjectFeatureFacade(features[i]);
689
        }
690
        return dynobjects;
691
    }
692
693 44253 jjdelcerro
    @Override
694 40435 jjdelcerro
    public DynObject getDynObjectAt(long index) throws BaseException {
695
        return new DynObjectFeatureFacade(getFeatureAt(index));
696
    }
697
698 44253 jjdelcerro
    @Override
699 41212 jjdelcerro
    public List asList() {
700
        return new FeaturePagingHelperList();
701
    }
702 41819 fdiaz
703 44253 jjdelcerro
    @Override
704 41212 jjdelcerro
    public List asListOfDynObjects() {
705
        return new DynObjectPagingHelperList();
706 41819 fdiaz
    }
707
708 41212 jjdelcerro
    private class FeaturePagingHelperList extends PagingHelperList {
709 44253 jjdelcerro
        @Override
710 41212 jjdelcerro
        public Object get(int i) {
711 44253 jjdelcerro
            return this.get64(i);
712
        }
713
714
        @Override
715
        public Object get64(long i) {
716 41212 jjdelcerro
            try {
717
                return getFeatureAt(i);
718 44253 jjdelcerro
            } catch (ConcurrentDataModificationException ex) {
719
                LOG.warn("ConcurrentDataModification error getting feature "+i+" of the list. Retrying reloading data.");
720
                try {
721
                    reload();
722
                } catch (BaseException e) {
723
                    LOG.warn("Error reloading data.", e);
724
                    throw new RuntimeException(e);
725
                }
726
                try {
727
                    return getFeatureAt(i);
728
                } catch (Exception e) {
729
                    LOG.warn("Error getting feature "+i+" of the list after reloading data.",e);
730
                    throw new RuntimeException(e);
731
                }
732 41212 jjdelcerro
            } catch (BaseException ex) {
733
                throw  new RuntimeException(ex);
734
            }
735
        }
736 44253 jjdelcerro
737
        @Override
738
        public Object set(int i, Object e) {
739
//            Feature newFeature = (Feature) e;
740
//            EditableFeature oldFeature = ((Feature) this.get(i)).getEditable();
741
//            oldFeature.copyFrom(newFeature);
742
//            update(oldFeature);
743
            return super.set(i, e);
744
        }
745
746
        @Override
747
        public Object remove(int i) {
748
//            Feature feature = (Feature) this.get(i);
749
//            delete(feature);
750
            return super.remove(i);
751
        }
752
753
        @Override
754
        public boolean add(Object e) {
755
//            EditableFeature feature = (EditableFeature) e;
756
//            insert(feature);
757
            return super.add(e);
758
        }
759 41212 jjdelcerro
    }
760 41819 fdiaz
761 41212 jjdelcerro
    private class DynObjectPagingHelperList extends PagingHelperList {
762 44253 jjdelcerro
        @Override
763 41212 jjdelcerro
        public Object get(int i) {
764 44253 jjdelcerro
            return this.get64(i);
765
        }
766
767
        @Override
768
        public Object get64(long position) {
769 41212 jjdelcerro
            try {
770 44253 jjdelcerro
                return getDynObjectAt(position);
771
            } catch (ConcurrentDataModificationException ex) {
772
                LOG.warn("ConcurrentDataModification error getting element "+position+" of the list. Retrying reloading data.");
773
                try {
774
                    reload();
775
                } catch (BaseException e) {
776
                    LOG.warn("Error reloading data.", e);
777
                    throw new RuntimeException(e);
778
                }
779
                try {
780
                    return getDynObjectAt(position);
781
                } catch (Exception e) {
782
                    LOG.warn("Error getting element "+position+" of the list after reloading data.",e);
783
                    throw new RuntimeException(e);
784
                }
785 41212 jjdelcerro
            } catch (BaseException ex) {
786
                throw  new RuntimeException(ex);
787
            }
788
        }
789 42775 jjdelcerro
790 41212 jjdelcerro
    }
791 41819 fdiaz
792 44253 jjdelcerro
    private abstract class PagingHelperList implements List, FacadeOfAFeaturePagingHelper, UnmodifiableBasicList, UnmodifiableBasicList64 {
793 41212 jjdelcerro
794 42775 jjdelcerro
        @Override
795
        public FeaturePagingHelper getFeaturePagingHelper() {
796
            return FeaturePagingHelperImpl.this;
797
        }
798 44253 jjdelcerro
799
        @Override
800
        public String toString() {
801
            return String.format("..(%d %ss)...", this.size(), featureStore.getName());
802
        }
803 42775 jjdelcerro
804 44253 jjdelcerro
        @Override
805
        public long size64() {
806 41212 jjdelcerro
            try {
807 44253 jjdelcerro
                return getFeatureSet(false).getSize();
808
            } catch (ConcurrentDataModificationException ex) {
809
                LOG.warn("ConcurrentDataModification error asking the size of the list. Retrying reloading data.");
810
                try {
811
                    reload();
812
                } catch (BaseException e) {
813
                    LOG.warn("Error reloading data.", e);
814
                    throw new RuntimeException(e);
815
                }
816
                try {
817
                    return getFeatureSet(false).getSize();
818
                } catch (DataException e) {
819
                    LOG.warn("Error asking the size of the list after reloading data.",e);
820
                    throw new RuntimeException(e);
821
                }
822 41212 jjdelcerro
            } catch (DataException ex) {
823
                throw  new RuntimeException(ex);
824
            }
825
        }
826
827 44253 jjdelcerro
        @Override
828
        public int size() {
829
            long sz = this.size64();
830
            if( sz>Integer.MAX_VALUE ) {
831
                sz = Integer.MAX_VALUE;
832
            }
833
            return (int) sz;
834
        }
835
836
        @Override
837 41212 jjdelcerro
        public boolean isEmpty() {
838
            try {
839
                return getFeatureSet(false).isEmpty();
840 41819 fdiaz
            } catch (ConcurrentDataModificationException ex) {
841 44253 jjdelcerro
                LOG.warn("ConcurrentDataModification error asking about the emptiness of the list. Retrying reloading data.");
842 41819 fdiaz
                try {
843
                    reload();
844
                } catch (BaseException e) {
845
                    LOG.warn("Error reloading data.", e);
846
                    throw new RuntimeException(e);
847
                }
848
                try {
849
                    return getFeatureSet(false).isEmpty();
850
                } catch (DataException e) {
851 44253 jjdelcerro
                    LOG.warn("Error asking about the emptiness of the list after reloading data.",e);
852 41819 fdiaz
                    throw new RuntimeException(e);
853
                }
854 44253 jjdelcerro
            } catch (DataException ex) {
855
                throw  new RuntimeException(ex);
856 41212 jjdelcerro
            }
857
        }
858
859 44253 jjdelcerro
        @Override
860 41212 jjdelcerro
        public Iterator iterator() {
861
            try {
862
                return getFeatureSet(false).fastIterator();
863 44253 jjdelcerro
            } catch (ConcurrentDataModificationException ex) {
864
                LOG.warn("ConcurrentDataModification error getting iterator of the list. Retrying reloading data.");
865
                try {
866
                    reload();
867
                } catch (BaseException e) {
868
                    LOG.warn("Error reloading data.", e);
869
                    throw new RuntimeException(e);
870
                }
871
                try {
872
                    return getFeatureSet(false).fastIterator();
873
                } catch (DataException e) {
874
                    LOG.warn("Error getting iterator of the list after reloading data.",e);
875
                    throw new RuntimeException(e);
876
                }
877 41212 jjdelcerro
            } catch (DataException ex) {
878
                throw  new RuntimeException(ex);
879
            }
880
        }
881
882 44253 jjdelcerro
        @Override
883 41212 jjdelcerro
        public boolean contains(Object o) {
884
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
885
        }
886
887 44253 jjdelcerro
        @Override
888 41212 jjdelcerro
        public Object[] toArray() {
889
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
890
        }
891
892 44253 jjdelcerro
        @Override
893 41212 jjdelcerro
        public Object[] toArray(Object[] ts) {
894
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
895
        }
896
897 44253 jjdelcerro
        @Override
898 41212 jjdelcerro
        public boolean add(Object e) {
899
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
900
        }
901
902 44253 jjdelcerro
        @Override
903 41212 jjdelcerro
        public boolean remove(Object o) {
904
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
905
        }
906
907 44253 jjdelcerro
        @Override
908 41212 jjdelcerro
        public boolean containsAll(Collection clctn) {
909
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
910
        }
911
912 44253 jjdelcerro
        @Override
913 41212 jjdelcerro
        public boolean addAll(Collection clctn) {
914
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
915
        }
916
917 44253 jjdelcerro
        @Override
918 41212 jjdelcerro
        public boolean addAll(int i, Collection clctn) {
919
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
920
        }
921
922 44253 jjdelcerro
        @Override
923 41212 jjdelcerro
        public boolean removeAll(Collection clctn) {
924
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
925
        }
926
927 44253 jjdelcerro
        @Override
928 41212 jjdelcerro
        public boolean retainAll(Collection clctn) {
929
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
930
        }
931
932 44253 jjdelcerro
        @Override
933 41212 jjdelcerro
        public void clear() {
934
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
935
        }
936
937 44253 jjdelcerro
        @Override
938 41212 jjdelcerro
        public Object set(int i, Object e) {
939
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
940
        }
941
942 44253 jjdelcerro
        @Override
943 41212 jjdelcerro
        public void add(int i, Object e) {
944
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
945
        }
946
947 44253 jjdelcerro
        @Override
948 41212 jjdelcerro
        public Object remove(int i) {
949
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
950
        }
951
952 44253 jjdelcerro
        @Override
953 41212 jjdelcerro
        public int indexOf(Object o) {
954
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
955
        }
956
957 44253 jjdelcerro
        @Override
958 41212 jjdelcerro
        public int lastIndexOf(Object o) {
959
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
960
        }
961
962 44253 jjdelcerro
        @Override
963 41212 jjdelcerro
        public ListIterator listIterator() {
964
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
965
        }
966
967 44253 jjdelcerro
        @Override
968 41212 jjdelcerro
        public ListIterator listIterator(int i) {
969
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
970
        }
971
972 44253 jjdelcerro
        @Override
973 41212 jjdelcerro
        public List subList(int i, int i1) {
974
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
975
        }
976 41819 fdiaz
977 44253 jjdelcerro
        @Override
978
        public List toList() {
979
            return this;
980
        }
981
982 41212 jjdelcerro
    }
983 40435 jjdelcerro
}