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 23675 cordinyana
/* 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 23772 jjdelcerro
 *
6 23675 cordinyana
 * 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 23772 jjdelcerro
 *
11 23675 cordinyana
 * 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 23772 jjdelcerro
 *
16 23675 cordinyana
 * 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 23772 jjdelcerro
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 23675 cordinyana
 * MA  02110-1301, USA.
20 23772 jjdelcerro
 *
21 23675 cordinyana
 */
22
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2008 {DiSiD Technologies}  {Create a JTable TableModel for a FeatureCollection}
26
 */
27 24496 jmvivo
package org.gvsig.fmap.dal.feature.paging;
28 23675 cordinyana
29
import java.util.Iterator;
30
31 24496 jmvivo
import org.gvsig.fmap.dal.exceptions.DataException;
32
import org.gvsig.fmap.dal.feature.*;
33 24023 cordinyana
import org.slf4j.Logger;
34
import org.slf4j.LoggerFactory;
35 23675 cordinyana
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 23786 cordinyana
 *
41 23930 cordinyana
 * 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 23786 cordinyana
 *
45 23675 cordinyana
 * @author <a href="mailto:cordin@disid.com">C?sar Ordi?ana</a>
46
 */
47 23786 cordinyana
public class FeaturePagingHelperImpl implements FeaturePagingHelper {
48 23675 cordinyana
49 24023 cordinyana
    final Logger logger = LoggerFactory
50
            .getLogger(FeaturePagingHelperImpl.class);
51 23930 cordinyana
52 23675 cordinyana
    private FeatureQuery query;
53
54 23934 cordinyana
    private FeatureSet featureSet;
55 23772 jjdelcerro
56 23675 cordinyana
    private FeatureStore featureStore;
57
58
    private int maxPageSize;
59
60 23934 cordinyana
    private long numPages;
61 23675 cordinyana
62 23934 cordinyana
    private long currentPage = -1;
63 23675 cordinyana
64
    private Feature[] values;
65
66
    /**
67 23934 cordinyana
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
68 23786 cordinyana
     *
69 23934 cordinyana
     * @param featureStore
70 23675 cordinyana
     *            to extract data from
71 23934 cordinyana
     * @throws DataException
72
     *             if there is an error initializing the helper
73 23675 cordinyana
     */
74 23714 cordinyana
    public FeaturePagingHelperImpl(FeatureStore featureStore)
75 23775 jjdelcerro
            throws DataException {
76 23675 cordinyana
        this(featureStore, DEFAULT_PAGE_SIZE);
77
    }
78
79
    /**
80 23934 cordinyana
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
81 23786 cordinyana
     *
82 23934 cordinyana
     * @param featureSet
83 23675 cordinyana
     *            to extract data from
84
     * @param pageSize
85
     *            the number of elements per page data
86 23934 cordinyana
     * @throws DataException
87
     *             if there is an error initializing the helper
88 23675 cordinyana
     */
89 23786 cordinyana
    public FeaturePagingHelperImpl(FeatureStore featureStore, int pageSize)
90
            throws DataException {
91
        this(featureStore, new FeatureQuery(featureStore
92
                .getDefaultFeatureType()), pageSize);
93 23675 cordinyana
    }
94
95
    /**
96 23934 cordinyana
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
97 23786 cordinyana
     *
98 23934 cordinyana
     * @param featureSet
99 23675 cordinyana
     *            to extract data from
100 23934 cordinyana
     * @throws DataException
101
     *             if there is an error initializing the helper
102 23675 cordinyana
     */
103 23714 cordinyana
    public FeaturePagingHelperImpl(FeatureStore featureStore,
104 23775 jjdelcerro
            FeatureQuery featureQuery) throws DataException {
105 23675 cordinyana
        this(featureStore, featureQuery, DEFAULT_PAGE_SIZE);
106
    }
107
108
    /**
109 23934 cordinyana
     * Constructs a FeaturePagingHelperImpl from data of a FeatureStore.
110 23786 cordinyana
     *
111 23934 cordinyana
     * @param featureSet
112 23675 cordinyana
     *            to extract data from
113
     * @param pageSize
114
     *            the number of elements per page data
115 23934 cordinyana
     * @throws DataException
116
     *             if there is an error initializing the helper
117 23675 cordinyana
     */
118 23714 cordinyana
    public FeaturePagingHelperImpl(FeatureStore featureStore,
119 23786 cordinyana
            FeatureQuery featureQuery, int pageSize) throws DataException {
120 23675 cordinyana
        this.maxPageSize = pageSize;
121
        this.featureStore = featureStore;
122
        this.query = featureQuery;
123
        loadFeatureCollection();
124
        setNumPages(calculateNumPages());
125 24023 cordinyana
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 23675 cordinyana
    }
132
133
    public int getMaxPageSize() {
134
        return maxPageSize;
135
    }
136
137 23930 cordinyana
    public void setMaxPageSize(int pageSize) throws DataException {
138 23675 cordinyana
        this.maxPageSize = pageSize;
139 23714 cordinyana
        reloadCurrentPage();
140 23675 cordinyana
    }
141
142 23934 cordinyana
    public long getNumPages() {
143 23675 cordinyana
        return numPages;
144
    }
145
146
    /**
147
     * Sets the number of pages.
148
     */
149 23934 cordinyana
    private void setNumPages(long numPages) {
150 23675 cordinyana
        this.numPages = numPages;
151
    }
152
153 23934 cordinyana
    public long getCurrentPage() {
154 23675 cordinyana
        return currentPage;
155
    }
156
157 23934 cordinyana
    public void setCurrentPage(long page) throws DataException {
158 23772 jjdelcerro
159 23930 cordinyana
        if (logger.isDebugEnabled()) {
160 24023 cordinyana
            logger.debug("Current page: {}", Long.toString(page));
161 23930 cordinyana
        }
162 23772 jjdelcerro
163 23675 cordinyana
        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 23786 cordinyana
                            + page + ", as the Collection only has "
172
                            + getNumPages() + " pages of Features");
173 23675 cordinyana
        }
174
        currentPage = page;
175
        loadCurrentPageData();
176
    }
177
178 23930 cordinyana
    public long getTotalSize() throws DataException {
179 23992 cordinyana
        return getFeatureSet().getSize();
180 23675 cordinyana
    }
181
182 23930 cordinyana
    public Feature getFeatureAt(long index) throws DataException {
183 23675 cordinyana
        // Check if we have currently loaded the viewed page data,
184
        // or we need to load a new one
185 23934 cordinyana
        long pageForIndex = (long) Math.floor(index / getMaxPageSize());
186 23675 cordinyana
187
        if (pageForIndex != getCurrentPage()) {
188
            setCurrentPage(pageForIndex);
189
        }
190 23772 jjdelcerro
191 23930 cordinyana
        long positionForIndex = index
192 23934 cordinyana
                - (getCurrentPage() * (long) getMaxPageSize());
193 23772 jjdelcerro
194 23930 cordinyana
        return values[(int) positionForIndex];
195 23675 cordinyana
    }
196 23772 jjdelcerro
197 23675 cordinyana
    public Feature[] getCurrentPageFeatures() {
198
        return values;
199
    }
200
201 23992 cordinyana
    public FeatureSet getFeatureSet() {
202 23934 cordinyana
        return featureSet;
203 23675 cordinyana
    }
204 23772 jjdelcerro
205 23930 cordinyana
    public void reloadCurrentPage() throws DataException {
206 23675 cordinyana
        setNumPages(calculateNumPages());
207 23714 cordinyana
        if (currentPage > -1) {
208
            loadCurrentPageData();
209
        }
210 23675 cordinyana
    }
211 23772 jjdelcerro
212 23775 jjdelcerro
    public void reload() throws DataException {
213 23714 cordinyana
        loadFeatureCollection();
214
        reloadCurrentPage();
215 23675 cordinyana
    }
216
217
    public FeatureStore getFeatureStore() {
218
        return featureStore;
219
    }
220
221 23714 cordinyana
    public FeatureQuery getFeatureQuery() {
222
        return query;
223
    }
224
225 23675 cordinyana
    /**
226
     * Calculates the number of pages.
227
     */
228 23934 cordinyana
    private long calculateNumPages() throws DataException {
229
        return ((long) Math.floor(getTotalSize() / getMaxPageSize())) + 1;
230 23675 cordinyana
    }
231
232
    /**
233
     * Loads all the Features of the current page.
234
     */
235 23930 cordinyana
    private void loadCurrentPageData() throws DataException {
236 23934 cordinyana
        long currentPage = getCurrentPage();
237 23675 cordinyana
        int currentPageSize;
238
        if (currentPage < (numPages - 1)) {
239
            currentPageSize = getMaxPageSize();
240
        } else {
241 23934 cordinyana
            currentPageSize = (int) (getTotalSize() - (currentPage * (long) getMaxPageSize()));
242 23675 cordinyana
        }
243
244
        values = new Feature[currentPageSize];
245
246 23930 cordinyana
        long firstPosition = currentPage * getMaxPageSize();
247 23675 cordinyana
248 24023 cordinyana
        if (logger.isDebugEnabled()) {
249
            logger.debug("Loading {} Features starting at position {}",
250
                    new Integer(currentPageSize), new Long(firstPosition));
251
        }
252
253 23992 cordinyana
        Iterator iter = getFeatureSet().iterator(firstPosition);
254 23675 cordinyana
        int i = 0;
255
        while (iter.hasNext() && i < currentPageSize) {
256
            values[i] = (Feature) iter.next();
257
            i++;
258
        }
259
    }
260 23772 jjdelcerro
261 23775 jjdelcerro
    private void loadFeatureCollection() throws DataException {
262 23934 cordinyana
        if (featureSet != null) {
263
            featureSet.dispose();
264 23714 cordinyana
        }
265 23934 cordinyana
        featureSet = getFeatureStore().getFeatureSet(query);
266 23675 cordinyana
    }
267
}