/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wms.featureinfo; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; import org.geotools.data.collection.ListFeatureCollection; import org.geotools.factory.Hints; import org.geotools.feature.FeatureIterator; import org.geotools.feature.collection.BaseFeatureCollection; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.Feature; import org.opengis.feature.type.FeatureType; /** * FeatureCollection implementation wrapping around a java.util.List. Derived from * {@link ListFeatureCollection}, but adapted to work with complex features too * * @see Hints#FEATURE_DETACHED * @author Oliver Gottwald * @author Jody * @author Andrea Aime - GeoSolutions * * @source $URL$ */ @SuppressWarnings("unchecked") class ListComplexFeatureCollection extends BaseFeatureCollection { /** wrapped list of features containing the contents */ private List<? extends Feature> list; /** Cached bounds */ private ReferencedEnvelope bounds = null; /** * Create a ListFeatureCollection around the provided list. The contents of the list should all * be of the provided schema for this to make sense. Please keep in mind the feature collection * control, no two Features in the list should have the same feature id, and you should not * insert the same feature more then once. * <p> * The provided list is directly used for storage, most feature collection operations just use a * simple iterator so there is no performance advantaged to be gained over using an ArrayList vs * a LinkedList (other then for the size() method of course). * * @param schema * @param list */ public ListComplexFeatureCollection(FeatureType schema, List<? extends Feature> list) { super(schema); this.list = list; } @Override public int size() { return list.size(); } @Override public FeatureIterator features() { return new ListComplexFeatureIterator(list); } @Override public synchronized ReferencedEnvelope getBounds() { if (bounds == null) { bounds = calculateBounds(); } return bounds; } /** * Calculate bounds from features * * */ private ReferencedEnvelope calculateBounds() { ReferencedEnvelope extent = new ReferencedEnvelope(); for (Feature feature : list) { if (feature == null) continue; ReferencedEnvelope bbox = ReferencedEnvelope.reference(feature.getBounds()); if (bbox == null || bbox.isEmpty() || bbox.isNull()) continue; extent.expandToInclude(bbox); } return new ReferencedEnvelope(extent, schema.getCoordinateReferenceSystem()); } @Override public boolean isEmpty() { return list.isEmpty(); } /** * SimpleFeatureIterator that will use collection close method. * * @author Jody */ private static class ListComplexFeatureIterator implements FeatureIterator { private Iterator<? extends Feature> iter; public ListComplexFeatureIterator(List<? extends Feature> features) { iter = features.iterator(); } @Override public void close() { if (iter instanceof FeatureIterator) { ((FeatureIterator<?>) iter).close(); } } @Override public boolean hasNext() { return iter.hasNext(); } @Override public Feature next() throws NoSuchElementException { return iter.next(); } } }