source: osm/applications/editors/josm/plugins/opendata/includes/org/geotools/data/collection/CollectionFeatureSource.java@ 28000

Last change on this file since 28000 was 28000, checked in by donvip, 12 years ago

Import new "opendata" JOSM plugin

File size: 9.1 KB
Line 
1package org.geotools.data.collection;
2
3import java.awt.RenderingHints.Key;
4import java.io.IOException;
5import java.util.ArrayList;
6import java.util.Arrays;
7import java.util.Collections;
8import java.util.Comparator;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Set;
12
13import org.geotools.data.DataAccess;
14import org.geotools.data.DataUtilities;
15import org.geotools.data.FeatureListener;
16import org.geotools.data.Query;
17import org.geotools.data.QueryCapabilities;
18import org.geotools.data.simple.SimpleFeatureCollection;
19import org.geotools.data.simple.SimpleFeatureSource;
20import org.geotools.data.store.EmptyFeatureCollection;
21import org.geotools.data.store.ReTypingFeatureCollection;
22import org.geotools.data.store.ReprojectingFeatureCollection;
23import org.geotools.feature.collection.DecoratingSimpleFeatureCollection;
24import org.geotools.feature.collection.FilteringSimpleFeatureCollection;
25import org.geotools.feature.collection.MaxSimpleFeatureCollection;
26import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
27import org.geotools.geometry.jts.ReferencedEnvelope;
28import org.opengis.feature.simple.SimpleFeature;
29import org.opengis.feature.simple.SimpleFeatureType;
30import org.opengis.feature.type.Name;
31import org.opengis.filter.Filter;
32import org.opengis.filter.sort.SortBy;
33
34/**
35 * This is a "port" of ContentFeatureSource to work with an iterator.
36 * <p>
37 * To use this class please "wrap" CollectionFeatureSource around your choice of FeatureCollection.
38 *
39 * <pre>
40 * SimpleFeatureCollection collection = new ListFeatureCollection(schema);
41 * collection.add(feature1);
42 * collection.add(feature2);
43 * FeatureSource source = new CollectionFeatureSource(collection);
44 * </pre>
45 * <p>
46 * Note to implementors: If you are performing "real I/O" please use ContentFeatureSource as it
47 * provides support for IOException.
48 *
49 * @author Jody
50 *
51 * @source $URL: http://svn.osgeo.org/geotools/branches/2.7.x/build/maven/javadoc/../../../modules/library/main/src/main/java/org/geotools/data/collection/CollectionFeatureSource.java $
52 */
53public class CollectionFeatureSource implements SimpleFeatureSource {
54 protected SimpleFeatureCollection collection;
55
56 /**
57 * observers
58 */
59 protected List<FeatureListener> listeners = null;
60
61 private QueryCapabilities capabilities;
62
63 private Set<Key> hints;
64
65 public CollectionFeatureSource(SimpleFeatureCollection collection) {
66 this.collection = collection;
67 }
68
69 public SimpleFeatureType getSchema() {
70 return collection.getSchema();
71 }
72
73 public synchronized void addFeatureListener(FeatureListener listener) {
74 if (listeners == null) {
75 listeners = Collections.synchronizedList(new ArrayList<FeatureListener>());
76 }
77 listeners.add(listener);
78 }
79
80 public synchronized void removeFeatureListener(FeatureListener listener) {
81 if (listeners == null) {
82 return;
83 }
84 listeners.remove(listener);
85 }
86
87 public ReferencedEnvelope getBounds() throws IOException {
88 return collection.getBounds();
89 }
90
91 public ReferencedEnvelope getBounds(Query query) throws IOException {
92 return getFeatures(query).getBounds();
93 }
94
95 public int getCount(Query query) throws IOException {
96 return getFeatures(query).size();
97 }
98
99 public DataAccess<SimpleFeatureType, SimpleFeature> getDataStore() {
100 throw new UnsupportedOperationException("CollectionFeatureSource is an inmemory wrapper");
101 }
102
103 public Name getName() {
104 return collection.getSchema().getName();
105 }
106
107 public synchronized QueryCapabilities getQueryCapabilities() {
108 if (capabilities == null) {
109 capabilities = new QueryCapabilities() {
110 public boolean isOffsetSupported() {
111 return true;
112 }
113
114 public boolean isReliableFIDSupported() {
115 return true;
116 }
117
118 public boolean supportsSorting(org.opengis.filter.sort.SortBy[] sortAttributes) {
119 return true;
120 }
121 };
122 }
123 return capabilities;
124 }
125
126 public synchronized Set<Key> getSupportedHints() {
127 if (hints == null) {
128 Set<Key> supports = new HashSet<Key>();
129 // supports.add( Hints.FEATURE_DETACHED );
130 hints = Collections.unmodifiableSet(supports);
131 }
132 return hints;
133 }
134
135 @Override
136 public String toString() {
137 StringBuilder buf = new StringBuilder();
138 buf.append("CollectionFeatureSource:");
139 buf.append(collection);
140 return buf.toString();
141 }
142
143 //
144 // GET FEATURES
145 // This forms the heart of the CollectionFeatureSource implementation
146 // Use: DataUtilities.mixQueries(this.query, query, "subCollection" ) as needed
147 //
148 public SimpleFeatureCollection getFeatures() throws IOException {
149 return getFeatures( Query.ALL );
150 }
151
152 public SimpleFeatureCollection getFeatures(Filter filter) {
153 Query query = new Query(getSchema().getTypeName(), filter);
154 return getFeatures(query);
155 }
156
157 public SimpleFeatureCollection getFeatures(Query query) {
158 query = DataUtilities.resolvePropertyNames(query, getSchema());
159 final int offset = query.getStartIndex() != null ? query.getStartIndex() : 0;
160 if (offset > 0 & query.getSortBy() == null) {
161 if (!getQueryCapabilities().supportsSorting(query.getSortBy())){
162 throw new IllegalStateException("Feature source does not support this sorting "
163 + "so there is no way a stable paging (offset/limit) can be performed");
164 }
165 Query copy = new Query(query);
166 copy.setSortBy(new SortBy[] { SortBy.NATURAL_ORDER });
167 query = copy;
168 }
169 SimpleFeatureCollection features = collection;
170 // step one: filter
171 if( query.getFilter() != null && query.getFilter().equals(Filter.EXCLUDE)){
172 return new EmptyFeatureCollection( getSchema() );
173 }
174 if (query.getFilter() != null && query.getFilter() != Filter.INCLUDE) {
175 features = new FilteringSimpleFeatureCollection(features, query.getFilter());
176 }
177 // step two: reproject
178 if (query.getCoordinateSystemReproject() != null) {
179 features = new ReprojectingFeatureCollection(features, query
180 .getCoordinateSystemReproject());
181 }
182 // step two sort! (note this makes a sorted copy)
183 if (query.getSortBy() != null && query.getSortBy().length != 0) {
184 SimpleFeature array[] = features.toArray(new SimpleFeature[features.size()]);
185 // Arrays sort is stable (not resorting equal elements)
186 for (SortBy sortBy : query.getSortBy()) {
187 Comparator<SimpleFeature> comparator = DataUtilities.sortComparator(sortBy);
188 Arrays.sort(array, comparator);
189 }
190 ArrayList<SimpleFeature> list = new ArrayList<SimpleFeature>(Arrays.asList(array));
191 features = new ListFeatureCollection(getSchema(), list);
192 }
193
194 // step three skip to start and return max number of fetaures
195 if (offset > 0 || !query.isMaxFeaturesUnlimited()) {
196 long max = Long.MAX_VALUE;
197 if (!query.isMaxFeaturesUnlimited()) {
198 max = query.getMaxFeatures();
199 }
200 features = new MaxSimpleFeatureCollection(features, offset, max);
201 }
202
203 // step four - retyping
204 // (It would be nice to do this earlier so as to not have all the baggage
205 // of unneeded attributes)
206 if (query.getPropertyNames() != Query.ALL_NAMES) {
207 // rebuild the type and wrap the reader
208 SimpleFeatureType schema = features.getSchema();
209 SimpleFeatureType target = SimpleFeatureTypeBuilder.retype(schema, query
210 .getPropertyNames());
211
212 // do an equals check because we may have needlessly retyped (that is,
213 // the subclass might be able to only partially retype)
214 if (!target.equals(schema)) {
215 features = new ReTypingFeatureCollection(features, target);
216 }
217 }
218 // Wrap up the results in a method that allows subCollection
219 return new SubCollection( query, features );
220 }
221
222 /**
223 * SubCollection for CollectionFeatureSource.
224 * <p>
225 * Will route any calls refining the feature collection back to CollectionFeatureSource. This is
226 * based on the success of ContentFeatureCollection.
227 * </p>
228 *
229 * @author Jody
230 */
231 protected class SubCollection extends DecoratingSimpleFeatureCollection {
232 private Query query;
233 protected SubCollection(Query query, SimpleFeatureCollection features) {
234 super(features);
235 this.query = query;
236 }
237 public SimpleFeatureCollection subCollection(Filter filter) {
238 Query q = new Query(getSchema().getTypeName(), filter);
239
240 Query subQuery = DataUtilities.mixQueries(query, q, q.getHandle() );
241 return CollectionFeatureSource.this.getFeatures( subQuery );
242 }
243 }
244}
Note: See TracBrowser for help on using the repository browser.