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