001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.feature.collection;
017:
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.Collections;
021: import java.util.Comparator;
022: import java.util.HashSet;
023: import java.util.Iterator;
024: import java.util.List;
025: import java.util.ListIterator;
026: import java.util.NoSuchElementException;
027: import java.util.Set;
028:
029: import org.geotools.data.collection.ResourceCollection;
030: import org.geotools.factory.CommonFactoryFinder;
031: import org.geotools.feature.Feature;
032: import org.geotools.feature.FeatureCollection;
033: import org.geotools.feature.FeatureList;
034: import org.geotools.filter.FilterFactoryFinder;
035: import org.opengis.filter.Filter;
036: import org.opengis.filter.FilterFactory;
037: import org.opengis.filter.Id;
038: import org.opengis.filter.expression.PropertyName;
039: import org.opengis.filter.sort.SortBy;
040: import org.opengis.filter.sort.SortOrder;
041:
042: public class SubFeatureList extends SubFeatureCollection implements
043: FeatureList, RandomFeatureAccess {
044: List sort;
045: List index;
046:
047: public SubFeatureList(FeatureCollection list, Filter filter) {
048: this (list, filter, null);
049: }
050:
051: public SubFeatureList(FeatureCollection list, SortBy sort) {
052: this (list, null, sort);
053: }
054:
055: /**
056: * Create a simple SubFeatureList with the provided
057: * filter.
058: *
059: * @param filter
060: */
061: public SubFeatureList(FeatureCollection list, Filter filter,
062: SortBy subSort) {
063: super (list, filter);
064: state = new SubFeatureState(list, this );
065: if (subSort == null) {
066: sort = Collections.EMPTY_LIST;
067: } else {
068: sort = new ArrayList();
069: if (collection instanceof SubFeatureList) {
070: SubFeatureList sorted = (SubFeatureList) collection;
071: sort.addAll(sorted.sort);
072: }
073: sort.add(subSort);
074: }
075: index = null;
076: }
077:
078: public SubFeatureList(FeatureCollection list, List order) {
079: super (list);
080: state = new SubFeatureState(list, this );
081: index = order;
082: filter = null;
083: }
084:
085: /** Lazy create a filter based on index */
086: protected Filter createFilter() {
087: FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
088: Set featureIds = new HashSet();
089: for (Iterator it = index.iterator(); it.hasNext();) {
090: featureIds.add(ff.featureId((String) it.next()));
091: }
092: Id fids = ff.id(featureIds);
093:
094: return fids;
095: }
096:
097: protected List index() {
098: if (index == null) {
099: index = createIndex();
100: }
101: return index;
102: }
103:
104: /** Put this SubFeatureList in touch with its inner index */
105: protected List createIndex() {
106: List fids = new ArrayList();
107: Iterator it = collection.iterator();
108: try {
109: while (it.hasNext()) {
110: Feature feature = (Feature) it.next();
111: if (filter.evaluate(feature)) {
112: fids.add(feature.getID());
113: }
114: }
115: if (sort != null && !sort.isEmpty()) {
116: final SortBy initialOrder = (SortBy) sort.get(sort
117: .size() - 1);
118: Collections.sort(fids, new Comparator() {
119: public int compare(Object key1, Object key2) {
120: Feature feature1 = getFeatureMember((String) key1);
121: Feature feature2 = getFeatureMember((String) key2);
122:
123: int compare = compare(feature1, feature2,
124: initialOrder);
125: if (compare == 0 && sort.size() > 1) {
126: for (int i = sort.size() - 1; compare == 0
127: && i >= 0; i--) {
128: compare = compare(feature1, feature2,
129: (SortBy) sort.get(i));
130: }
131: }
132: return compare;
133: }
134:
135: protected int compare(Feature feature1,
136: Feature feature2, SortBy order) {
137: PropertyName name = order.getPropertyName();
138: Comparable value1 = (Comparable) name
139: .evaluate(feature1);
140: Comparable value2 = (Comparable) name
141: .evaluate(feature2);
142:
143: if (order.getSortOrder() == SortOrder.ASCENDING) {
144: return value1.compareTo(value2);
145: } else
146: return value2.compareTo(value1);
147: }
148: });
149: }
150: } finally {
151: collection.close(it);
152: }
153: return fids;
154: }
155:
156: public boolean addAll(int index, Collection c) {
157: boolean modified = false;
158: Iterator e = c.iterator();
159: try {
160: while (e.hasNext()) {
161: add(index++, e.next());
162: modified = true;
163: }
164: return modified;
165: } finally {
166: if (c instanceof ResourceCollection) {
167: ((ResourceCollection) c).close(e);
168: }
169: }
170: }
171:
172: public Object get(int index) {
173: if (collection instanceof RandomFeatureAccess) {
174: RandomFeatureAccess random = (RandomFeatureAccess) collection;
175: String id = (String) index().get(index);
176: random.getFeatureMember(id);
177: }
178: Iterator it = iterator();
179: try {
180: for (int i = 0; it.hasNext(); i++) {
181: Feature feature = (Feature) it.next();
182: if (i == index) {
183: return feature;
184: }
185: }
186: throw new IndexOutOfBoundsException();
187: } finally {
188: close(it);
189: }
190: }
191:
192: public Object set(int index, Object feature) {
193: throw new UnsupportedOperationException();
194: }
195:
196: public void add(int index, Object feature) {
197: throw new UnsupportedOperationException();
198: }
199:
200: public Object remove(int index) {
201: String fid = (String) index().get(index);
202: Feature feature = getFeatureMember(fid);
203:
204: if (collection.remove(feature))
205: return feature;
206:
207: return null;
208: }
209:
210: public int indexOf(Object o) {
211: Feature feature = (Feature) o;
212: return index().indexOf(feature.getID());
213: }
214:
215: public int lastIndexOf(Object o) {
216: Feature feature = (Feature) o;
217: return index().lastIndexOf(feature.getID());
218: }
219:
220: public ListIterator listIterator() {
221: return listIterator(0);
222: }
223:
224: public ListIterator listIterator(final int index) {
225: if (index < 0 || index > size())
226: throw new IndexOutOfBoundsException("Index: " + index);
227: ListIterator iterator = openIterator(index);
228: open.add(iterator);
229: return iterator;
230: }
231:
232: public ListIterator openIterator(final int index) {
233: return new SubListItr(index);
234: }
235:
236: class SubListItr implements ListIterator {
237: ListIterator it;
238: String fid;
239:
240: public SubListItr(int fromIndex) {
241: it = index().subList(fromIndex, index.size())
242: .listIterator();
243: }
244:
245: public boolean hasNext() {
246: return it.hasNext();
247: }
248:
249: public Object next() {
250: fid = (String) it.next();
251: return getFeatureMember(fid);
252: }
253:
254: public void remove() {
255: it.remove();
256: if (fid == null)
257: throw new IllegalStateException();
258: removeFeatureMember(fid);
259: index.remove(fid);
260: }
261:
262: public boolean hasPrevious() {
263: return it.hasPrevious();
264: }
265:
266: public Object previous() {
267: fid = (String) it.previous();
268: return getFeatureMember(fid);
269: }
270:
271: public int nextIndex() {
272: return it.nextIndex();
273: }
274:
275: public int previousIndex() {
276: return it.previousIndex();
277: }
278:
279: public void set(Object arg0) {
280: throw new UnsupportedOperationException();
281: }
282:
283: public void add(Object feature) {
284: SubFeatureList.this .add(it.nextIndex() - 1, feature);
285: }
286: }
287:
288: //
289: // Fature Collection methods
290: //
291: /**
292: * Sublist of this sublist!
293: * <p>
294: * Implementation will ensure this does not get out of hand, order
295: * is maintained and only indexed once.
296: * </p>
297: */
298: public FeatureList subList(Filter subfilter) {
299: return new SubFeatureList(this , subfilter);
300: }
301:
302: //
303: // RandomFeatureAccess
304: //
305:
306: public Feature getFeatureMember(String id)
307: throws NoSuchElementException {
308: int position = index.indexOf(id);
309: if (position == -1) {
310: throw new NoSuchElementException(id);
311: }
312: if (collection instanceof RandomFeatureAccess) {
313: RandomFeatureAccess random = (RandomFeatureAccess) collection;
314: random.getFeatureMember(id);
315: }
316: return (Feature) get(position);
317: }
318:
319: public Feature removeFeatureMember(String id) {
320: int position = index.indexOf(id);
321: if (position == -1) {
322: throw new NoSuchElementException(id);
323: }
324: if (collection instanceof RandomFeatureAccess) {
325: RandomFeatureAccess random = (RandomFeatureAccess) collection;
326: if (index != null)
327: index.remove(id);
328: return random.removeFeatureMember(id);
329: }
330: return (Feature) remove(position);
331: }
332:
333: //
334: // FeatureList
335: //
336: public List subList(int fromIndex, int toIndex) {
337: return new SubFeatureList(this , index().subList(fromIndex,
338: toIndex));
339: }
340:
341: public FeatureList sort(SortBy order) {
342: return super.sort(order);
343: }
344:
345: }
|