1 |
mojays |
2 |
/* |
2 |
|
|
* GeoTools - OpenSource mapping toolkit |
3 |
|
|
* http://geotools.org |
4 |
|
|
* (C) 2005-2006, GeoTools Project Managment Committee (PMC) |
5 |
|
|
* |
6 |
|
|
* This library is free software; you can redistribute it and/or |
7 |
|
|
* modify it under the terms of the GNU Lesser General Public |
8 |
|
|
* License as published by the Free Software Foundation; |
9 |
|
|
* version 2.1 of the License. |
10 |
|
|
* |
11 |
|
|
* This library 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 GNU |
14 |
|
|
* Lesser General Public License for more details. |
15 |
|
|
*/ |
16 |
|
|
package org.geotools.feature.collection; |
17 |
|
|
|
18 |
|
|
import java.io.IOException; |
19 |
|
|
import java.util.Iterator; |
20 |
|
|
|
21 |
|
|
import org.geotools.data.FeatureReader; |
22 |
|
|
import org.geotools.data.collection.DelegateFeatureReader; |
23 |
|
|
import org.geotools.feature.CollectionListener; |
24 |
|
|
import org.geotools.feature.Feature; |
25 |
|
|
import org.geotools.feature.FeatureCollection; |
26 |
|
|
import org.geotools.feature.FeatureIterator; |
27 |
|
|
import org.geotools.feature.FeatureList; |
28 |
|
|
import org.geotools.feature.FeatureType; |
29 |
|
|
import org.geotools.feature.IllegalAttributeException; |
30 |
|
|
import org.geotools.feature.visitor.FeatureVisitor; |
31 |
|
|
import org.geotools.filter.Filter; |
32 |
|
|
import org.geotools.filter.SortBy; |
33 |
|
|
import org.geotools.util.ProgressListener; |
34 |
|
|
|
35 |
|
|
import com.vividsolutions.jts.geom.Envelope; |
36 |
|
|
import com.vividsolutions.jts.geom.Geometry; |
37 |
|
|
|
38 |
|
|
/** |
39 |
|
|
* <b>Xulu:<br> |
40 |
|
|
* Code taken from gt-2.3.4 to optimize the {@link #size()} method! |
41 |
|
|
* The original variant always iterates ALL features at every call!.</b><br><br> |
42 |
|
|
* |
43 |
|
|
* Used as a reasonable default implementation for subCollection. |
44 |
|
|
* <p> |
45 |
|
|
* Note: to implementors, this is not optimal, please do your own |
46 |
|
|
* thing - your users will thank you. |
47 |
|
|
* </p> |
48 |
|
|
* |
49 |
|
|
* @author Jody Garnett, Refractions Research, Inc. |
50 |
|
|
* |
51 |
|
|
* @source $URL: http://svn.geotools.org/geotools/branches/2.3.x/module/main/src/org/geotools/feature/collection/SubFeatureCollection.java $ |
52 |
|
|
*/ |
53 |
|
|
public class SubFeatureCollection extends AbstractResourceCollection implements FeatureCollection { |
54 |
|
|
// Xulu-01.sn |
55 |
|
|
private int size = -1; |
56 |
|
|
// Xulu-01.en |
57 |
|
|
|
58 |
|
|
/** Filter */ |
59 |
|
|
protected Filter filter; |
60 |
|
|
|
61 |
|
|
/** Origional Collection */ |
62 |
|
|
protected FeatureCollection collection; |
63 |
|
|
|
64 |
|
|
protected FeatureState state; |
65 |
|
|
|
66 |
|
|
public SubFeatureCollection(FeatureCollection collection ) { |
67 |
|
|
this( collection, null ); |
68 |
|
|
} |
69 |
|
|
public SubFeatureCollection(FeatureCollection collection, Filter subfilter ){ |
70 |
|
|
if (subfilter != null && subfilter.equals(Filter.ALL)) { |
71 |
|
|
throw new IllegalArgumentException("A subcollection with Filter.ALL is a null operation"); |
72 |
|
|
} |
73 |
|
|
if (subfilter != null && subfilter.equals(Filter.NONE)) { |
74 |
|
|
throw new IllegalArgumentException("A subcollection with Filter.NONE should be a FeatureCollectionEmpty"); |
75 |
|
|
} |
76 |
|
|
if( subfilter != null && (collection instanceof SubFeatureCollection)){ |
77 |
|
|
SubFeatureCollection filtered = (SubFeatureCollection) collection; |
78 |
|
|
this.collection = filtered.collection; |
79 |
|
|
this.filter = filtered.filter().and(subfilter); |
80 |
|
|
} else { |
81 |
|
|
this.collection = collection; |
82 |
|
|
this.filter = subfilter; |
83 |
|
|
} |
84 |
|
|
state = new SubFeatureState( this.collection, this ); |
85 |
|
|
} |
86 |
|
|
|
87 |
|
|
protected Filter filter(){ |
88 |
|
|
if( filter == null ){ |
89 |
|
|
filter = createFilter(); |
90 |
|
|
} |
91 |
|
|
return filter; |
92 |
|
|
} |
93 |
|
|
/** Override to implement subsetting */ |
94 |
|
|
protected Filter createFilter(){ |
95 |
|
|
return Filter.NONE; |
96 |
|
|
} |
97 |
|
|
|
98 |
|
|
public FeatureType getFeatureType() { |
99 |
|
|
return state.getFeatureType(); |
100 |
|
|
} |
101 |
|
|
|
102 |
|
|
public FeatureIterator features() { |
103 |
|
|
return new DelegateFeatureIterator( this, iterator() ); |
104 |
|
|
} |
105 |
|
|
|
106 |
|
|
public void closeIterator(Iterator iterator) { |
107 |
|
|
if( iterator == null ) return; |
108 |
|
|
|
109 |
|
|
if( iterator instanceof FilteredIterator){ |
110 |
|
|
FilteredIterator filtered = (FilteredIterator) iterator; |
111 |
|
|
filtered.close(); |
112 |
|
|
} |
113 |
|
|
} |
114 |
|
|
public void close(FeatureIterator close) { |
115 |
|
|
if( close != null ) close.close(); |
116 |
|
|
} |
117 |
|
|
|
118 |
|
|
// |
119 |
|
|
// Feature methods |
120 |
|
|
// |
121 |
|
|
public String getID() { |
122 |
|
|
return state.getId(); |
123 |
|
|
} |
124 |
|
|
|
125 |
|
|
public Envelope getBounds(){ |
126 |
|
|
return state.getBounds(); |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
public Geometry getDefaultGeometry() { |
130 |
|
|
return state.getDefaultGeometry(); |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
public void setDefaultGeometry(Geometry g) throws IllegalAttributeException { |
134 |
|
|
state.setDefaultGeometry( g ); |
135 |
|
|
} |
136 |
|
|
public void addListener(CollectionListener listener) throws NullPointerException { |
137 |
|
|
state.addListener( listener ); |
138 |
|
|
} |
139 |
|
|
|
140 |
|
|
public void removeListener(CollectionListener listener) throws NullPointerException { |
141 |
|
|
state.removeListener( listener ); |
142 |
|
|
} |
143 |
|
|
|
144 |
|
|
public FeatureCollection getParent() { |
145 |
|
|
return state.getParent(); |
146 |
|
|
} |
147 |
|
|
|
148 |
|
|
public void setParent(FeatureCollection collection) { |
149 |
|
|
state.setParent( collection ); |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
public Object[] getAttributes(Object[] attributes) { |
153 |
|
|
return state.getAttributes( attributes ); |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
public Object getAttribute(String xPath) { |
157 |
|
|
return state.getAttribute( xPath ); |
158 |
|
|
} |
159 |
|
|
|
160 |
|
|
public Object getAttribute(int index) { |
161 |
|
|
return state.getAttribute( index ); |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
public void setAttribute(int position, Object val) throws IllegalAttributeException, ArrayIndexOutOfBoundsException { |
165 |
|
|
state.setAttribute( position, val ); |
166 |
|
|
} |
167 |
|
|
public int getNumberOfAttributes() { |
168 |
|
|
return state.getNumberOfAttributes(); |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
public void setAttribute(String xPath, Object attribute) throws IllegalAttributeException { |
172 |
|
|
state.setAttribute( xPath, attribute ); |
173 |
|
|
} |
174 |
|
|
|
175 |
|
|
// |
176 |
|
|
// |
177 |
|
|
// |
178 |
|
|
public FeatureCollection subCollection(Filter filter) { |
179 |
|
|
if (filter.equals(Filter.NONE)) { |
180 |
|
|
return this; |
181 |
|
|
} |
182 |
|
|
if (filter.equals(Filter.ALL)) { |
183 |
|
|
// TODO implement EmptyFeatureCollection( schema ) |
184 |
|
|
} |
185 |
|
|
return new SubFeatureCollection(this, filter); |
186 |
|
|
} |
187 |
|
|
|
188 |
|
|
public int size() { |
189 |
|
|
//Xulu-01.sn |
190 |
|
|
if ( this.size >= 0 ) |
191 |
|
|
return this.size; |
192 |
|
|
//Xulu-01.en |
193 |
|
|
int count = 0; |
194 |
|
|
Iterator i = null; |
195 |
|
|
try { |
196 |
|
|
for( i = iterator(); i.hasNext(); count++) i.next(); |
197 |
|
|
} |
198 |
|
|
finally { |
199 |
|
|
close( i ); |
200 |
|
|
} |
201 |
|
|
//Xulu-01.sn |
202 |
|
|
this.size = count; |
203 |
|
|
//Xulu-01.en |
204 |
|
|
|
205 |
|
|
return count; |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
public boolean isEmpty() { |
209 |
|
|
Iterator iterator = iterator(); |
210 |
|
|
try { |
211 |
|
|
return iterator.hasNext(); |
212 |
|
|
} |
213 |
|
|
finally { |
214 |
|
|
close( iterator ); |
215 |
|
|
} |
216 |
|
|
} |
217 |
|
|
|
218 |
|
|
public Iterator openIterator() { |
219 |
|
|
return new FilteredIterator( collection, filter() ); |
220 |
|
|
} |
221 |
|
|
|
222 |
|
|
|
223 |
|
|
public FeatureType getSchema() { |
224 |
|
|
return collection.getSchema(); |
225 |
|
|
} |
226 |
|
|
|
227 |
|
|
/** |
228 |
|
|
* Accepts a visitor, which then visits each feature in the collection. |
229 |
|
|
* @throws IOException |
230 |
|
|
*/ |
231 |
|
|
public void accepts(FeatureVisitor visitor, ProgressListener progress ) throws IOException { |
232 |
|
|
Iterator iterator = null; |
233 |
|
|
// if( progress == null ) progress = new NullProgressListener(); |
234 |
|
|
try{ |
235 |
|
|
float size = size(); |
236 |
|
|
float position = 0; |
237 |
|
|
progress.started(); |
238 |
|
|
for( iterator = iterator(); !progress.isCanceled() && iterator.hasNext(); progress.progress( position++/size )){ |
239 |
|
|
try { |
240 |
|
|
Feature feature = (Feature) iterator.next(); |
241 |
|
|
visitor.visit(feature); |
242 |
|
|
} |
243 |
|
|
catch( Exception erp ){ |
244 |
|
|
progress.exceptionOccurred( erp ); |
245 |
|
|
} |
246 |
|
|
} |
247 |
|
|
} |
248 |
|
|
finally { |
249 |
|
|
progress.complete(); |
250 |
|
|
close( iterator ); |
251 |
|
|
} |
252 |
|
|
} |
253 |
|
|
|
254 |
|
|
public FeatureReader reader() throws IOException { |
255 |
|
|
return new DelegateFeatureReader( getSchema(), features() ); |
256 |
|
|
} |
257 |
|
|
|
258 |
|
|
public int getCount() throws IOException { |
259 |
|
|
return size(); |
260 |
|
|
} |
261 |
|
|
|
262 |
|
|
public FeatureCollection collection() throws IOException { |
263 |
|
|
return this; |
264 |
|
|
} |
265 |
|
|
|
266 |
|
|
public FeatureList sort(SortBy order) { |
267 |
|
|
return null; |
268 |
|
|
} |
269 |
|
|
|
270 |
|
|
public void purge() { |
271 |
|
|
collection.purge(); |
272 |
|
|
} |
273 |
|
|
} |