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