Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_dal / src / org / gvsig / fmap / dal / feature / paging / FeaturePagingHelperImpl.java @ 24496

History | View | Annotate | Download (8.02 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Gobernment (CIT)
5
 *
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
 * as published by the Free Software Foundation; either version 2
9
 * 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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {Create a JTable TableModel for a FeatureCollection}
26
 */
27
package org.gvsig.fmap.dal.feature.paging;
28

    
29
import java.util.Iterator;
30

    
31
import org.gvsig.fmap.dal.exceptions.DataException;
32
import org.gvsig.fmap.dal.feature.*;
33
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35

    
36
/**
37
 * Helper class to access the values of a FeatureCollection by position. Handles
38
 * pagination automatically to avoid filling the memory in case of big
39
 * collections.
40
 * 
41
 * TODO: evaluate if its more convenient to read values in the background when
42
 * the returned value is near the end of the page, instead of loading a page on
43
 * demand.
44
 * 
45
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
46
 */
47
public class FeaturePagingHelperImpl implements FeaturePagingHelper {
48

    
49
    final Logger logger = LoggerFactory
50
            .getLogger(FeaturePagingHelperImpl.class);
51

    
52
    private FeatureQuery query;
53

    
54
    private FeatureSet featureSet;
55

    
56
    private FeatureStore featureStore;
57

    
58
    private int maxPageSize;
59

    
60
    private long numPages;
61

    
62
    private long currentPage = -1;
63

    
64
    private Feature[] values;
65

    
66
    /**
67
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
68
     * 
69
     * @param featureStore
70
     *            to extract data from
71
     * @throws DataException
72
     *             if there is an error initializing the helper
73
     */
74
    public FeaturePagingHelperImpl(FeatureStore featureStore)
75
            throws DataException {
76
        this(featureStore, DEFAULT_PAGE_SIZE);
77
    }
78

    
79
    /**
80
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
81
     * 
82
     * @param featureSet
83
     *            to extract data from
84
     * @param pageSize
85
     *            the number of elements per page data
86
     * @throws DataException
87
     *             if there is an error initializing the helper
88
     */
89
    public FeaturePagingHelperImpl(FeatureStore featureStore, int pageSize)
90
            throws DataException {
91
        this(featureStore, new FeatureQuery(featureStore
92
                .getDefaultFeatureType()), pageSize);
93
    }
94

    
95
    /**
96
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
97
     * 
98
     * @param featureSet
99
     *            to extract data from
100
     * @throws DataException
101
     *             if there is an error initializing the helper
102
     */
103
    public FeaturePagingHelperImpl(FeatureStore featureStore,
104
            FeatureQuery featureQuery) throws DataException {
105
        this(featureStore, featureQuery, DEFAULT_PAGE_SIZE);
106
    }
107

    
108
    /**
109
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
110
     * 
111
     * @param featureSet
112
     *            to extract data from
113
     * @param pageSize
114
     *            the number of elements per page data
115
     * @throws DataException
116
     *             if there is an error initializing the helper
117
     */
118
    public FeaturePagingHelperImpl(FeatureStore featureStore,
119
            FeatureQuery featureQuery, int pageSize) throws DataException {
120
        this.maxPageSize = pageSize;
121
        this.featureStore = featureStore;
122
        this.query = featureQuery;
123
        loadFeatureCollection();
124
        setNumPages(calculateNumPages());
125

    
126
        if (logger.isDebugEnabled()) {
127
            logger.debug("FeaturePagingHelperImpl created with {} pages, "
128
                    + "and a page size of {}", new Long(numPages), new Integer(
129
                    pageSize));
130
        }
131
    }
132

    
133
    public int getMaxPageSize() {
134
        return maxPageSize;
135
    }
136

    
137
    public void setMaxPageSize(int pageSize) throws DataException {
138
        this.maxPageSize = pageSize;
139
        reloadCurrentPage();
140
    }
141

    
142
    public long getNumPages() {
143
        return numPages;
144
    }
145

    
146
    /**
147
     * Sets the number of pages.
148
     */
149
    private void setNumPages(long numPages) {
150
        this.numPages = numPages;
151
    }
152

    
153
    public long getCurrentPage() {
154
        return currentPage;
155
    }
156

    
157
    public void setCurrentPage(long page) throws DataException {
158

    
159
        if (logger.isDebugEnabled()) {
160
            logger.debug("Current page: {}", Long.toString(page));
161
        }
162

    
163
        if (page < 0) {
164
            throw new IndexOutOfBoundsException(
165
                    "Error, unable to set helper current page to a "
166
                            + "negative value: " + page);
167
        }
168
        if (page >= getNumPages()) {
169
            throw new IndexOutOfBoundsException(
170
                    "Error, unable to set helper current page to the page num. "
171
                            + page + ", as the Collection only has "
172
                            + getNumPages() + " pages of Features");
173
        }
174
        currentPage = page;
175
        loadCurrentPageData();
176
    }
177

    
178
    public long getTotalSize() throws DataException {
179
        return getFeatureSet().getSize();
180
    }
181

    
182
    public Feature getFeatureAt(long index) throws DataException {
183
        // Check if we have currently loaded the viewed page data,
184
        // or we need to load a new one
185
        long pageForIndex = (long) Math.floor(index / getMaxPageSize());
186

    
187
        if (pageForIndex != getCurrentPage()) {
188
            setCurrentPage(pageForIndex);
189
        }
190

    
191
        long positionForIndex = index
192
                - (getCurrentPage() * (long) getMaxPageSize());
193

    
194
        return values[(int) positionForIndex];
195
    }
196

    
197
    public Feature[] getCurrentPageFeatures() {
198
        return values;
199
    }
200

    
201
    public FeatureSet getFeatureSet() {
202
        return featureSet;
203
    }
204

    
205
    public void reloadCurrentPage() throws DataException {
206
        setNumPages(calculateNumPages());
207
        if (currentPage > -1) {
208
            loadCurrentPageData();
209
        }
210
    }
211

    
212
    public void reload() throws DataException {
213
        loadFeatureCollection();
214
        reloadCurrentPage();
215
    }
216

    
217
    public FeatureStore getFeatureStore() {
218
        return featureStore;
219
    }
220

    
221
    public FeatureQuery getFeatureQuery() {
222
        return query;
223
    }
224

    
225
    /**
226
     * Calculates the number of pages.
227
     */
228
    private long calculateNumPages() throws DataException {
229
        return ((long) Math.floor(getTotalSize() / getMaxPageSize())) + 1;
230
    }
231

    
232
    /**
233
     * Loads all the Features of the current page.
234
     */
235
    private void loadCurrentPageData() throws DataException {
236
        long currentPage = getCurrentPage();
237
        int currentPageSize;
238
        if (currentPage < (numPages - 1)) {
239
            currentPageSize = getMaxPageSize();
240
        } else {
241
            currentPageSize = (int) (getTotalSize() - (currentPage * (long) getMaxPageSize()));
242
        }
243

    
244
        values = new Feature[currentPageSize];
245

    
246
        long firstPosition = currentPage * getMaxPageSize();
247

    
248
        if (logger.isDebugEnabled()) {
249
            logger.debug("Loading {} Features starting at position {}",
250
                    new Integer(currentPageSize), new Long(firstPosition));
251
        }
252

    
253
        Iterator iter = getFeatureSet().iterator(firstPosition);
254
        int i = 0;
255
        while (iter.hasNext() && i < currentPageSize) {
256
            values[i] = (Feature) iter.next();
257
            i++;
258
        }
259
    }
260

    
261
    private void loadFeatureCollection() throws DataException {
262
        if (featureSet != null) {
263
            featureSet.dispose();
264
        }
265
        featureSet = getFeatureStore().getFeatureSet(query);
266
    }
267
}