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 | } |