001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-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.data.store;
017:
018: import java.io.IOException;
019: import java.util.logging.Logger;
020:
021: import com.vividsolutions.jts.geom.Envelope;
022: import org.opengis.feature.simple.SimpleTypeFactory;
023: import org.opengis.filter.Filter;
024: import org.geotools.data.DataStore;
025: import org.geotools.data.FeatureListener;
026: import org.geotools.data.FeatureSource;
027: import org.geotools.data.Query;
028: import org.geotools.data.Transaction;
029: import org.geotools.feature.FeatureCollection;
030: import org.geotools.feature.FeatureType;
031:
032: /**
033: * Abstract implementation of FeatureSource.
034: * <p>
035: * Implementations are based around feature collections. Subclasses must
036: * implement the following methods to provide feature collection based data
037: * access:
038: * <ul>
039: * <li>{@link #all(ContentState)}: Access to entire dataset
040: * <li>{@link #filtered(ContentState, Filter)}: Access to filtered dataset
041: * </ul>
042: * In addition, subclasses must implement {@link #buildFeatureType(SimpleTypeFactory)}
043: * in which constructs the feature type for the feature.
044: *
045: * @author Jody Garnett, Refractions Research Inc.
046: * @author Justin Deoliveira, The Open Planning Project
047: */
048: public abstract class ContentFeatureSource implements FeatureSource {
049: /**
050: * The entry for the feautre source.
051: */
052: protected ContentEntry entry;
053:
054: /**
055: * The transaction to work from
056: */
057: protected Transaction transaction;
058:
059: public ContentFeatureSource(ContentEntry entry) {
060: this .entry = entry;
061: }
062:
063: public ContentEntry getEntry() {
064: return entry;
065: }
066:
067: public void setTransaction(Transaction transaction) {
068: this .transaction = transaction;
069: }
070:
071: public Transaction getTransaction() {
072: return transaction;
073: }
074:
075: public final DataStore getDataStore() {
076: return entry.getDataStore();
077: }
078:
079: public final FeatureType getSchema() {
080: ContentState state = entry.getState(transaction);
081: FeatureType featureType = state.getMemberType();
082:
083: if (featureType == null) {
084: //build and cache it
085: synchronized (state) {
086: if (featureType == null) {
087: try {
088: featureType = buildFeatureType();
089: } catch (IOException e) {
090: throw new RuntimeException(e);
091: }
092: state.setMemberType(featureType);
093: }
094: }
095: }
096: return featureType;
097: }
098:
099: public final Envelope getBounds() throws IOException {
100: return all(entry.getState(transaction)).getBounds();
101: }
102:
103: public final Envelope getBounds(Query query) throws IOException {
104: return filtered(entry.getState(transaction), query.getFilter())
105: .getBounds();
106: }
107:
108: public final int getCount(Query query) throws IOException {
109: return filtered(entry.getState(transaction), query.getFilter())
110: .size();
111: }
112:
113: public final FeatureCollection getFeatures() throws IOException {
114: return getFeatures(Query.ALL);
115: }
116:
117: public final FeatureCollection getFeatures(Query query)
118: throws IOException {
119: FeatureCollection features = getFeatures(query.getFilter());
120:
121: if (query.getCoordinateSystemReproject() != null) {
122: // features = features.reproject( query.getCoordinateSystemReproject() );
123: }
124:
125: if (query.getCoordinateSystem() != null) {
126: // features = features.toCRS( query.getCoordinateSystem() );
127: }
128:
129: if (query.getMaxFeatures() != Integer.MAX_VALUE) {
130: // features = (FeatureCollection) features.sort(
131: // SortBy.NATURAL_ORDER).subList(0, query.getMaxFeatures());
132: }
133:
134: if (query.getNamespace() != null) {
135: // features = features.toNamespace( query.getNamespace() );
136: }
137:
138: if (query.getPropertyNames() != Query.ALL_NAMES) {
139: // features = features.reType( query.getPropertyNames() );
140: }
141:
142: return features;
143: }
144:
145: public final FeatureCollection getFeatures(Filter filter)
146: throws IOException {
147: if ((filter == null) || (filter == Filter.INCLUDE)) {
148: return all(entry.getState(transaction));
149: }
150:
151: return filtered(entry.getState(transaction), filter);
152: }
153:
154: public final void addFeatureListener(FeatureListener listener) {
155: entry.getState(transaction).addListener(listener);
156: }
157:
158: public final void removeFeatureListener(FeatureListener listener) {
159: entry.getState(transaction).removeListener(listener);
160: }
161:
162: //
163: // Internal API
164: //
165: /**
166: * Returns the data store logger.
167: */
168: public Logger getLogger() {
169: return ((ContentDataStore) getDataStore()).getLogger();
170: }
171:
172: /**
173: * Creates a feature type for the entry.
174: * <p>
175: * An implementation of this method should create a new instance of
176: * {@link SimpleTypeBuilder}, injecting it with the factory provided by
177: * the datastore via. Example.
178: * <pre>
179: * <code>
180: * SimpleTypeBuilder builder = new SimpleTypeBuilder( entry.getDataStore().getTypeFactory());
181: * ...
182: * </code>
183: * </pre>
184: */
185: protected abstract FeatureType buildFeatureType()
186: throws IOException;
187:
188: /**
189: * FeatureCollection representing the entire contents.
190: * <p>
191: * Available via getFeatureSource():
192: * <ul>
193: * <li>getFeatures()
194: * <li>getFeatures( Filter.INCLUDES )
195: * </ul>
196: *
197: * @param state
198: * @return all content
199: */
200: protected abstract FeatureCollection all(ContentState state);
201:
202: /**
203: * FeatureCollection representing a subset of available content.
204: * <p>
205: * Available via getFeatureSource():
206: * <ul>
207: * <li>getFeatures().filter( filter )
208: * <li>getFeatures( filter )
209: * </ul>
210: * @param state
211: * @param filter
212: * @return subset of content
213: */
214: protected abstract FeatureCollection filtered(ContentState state,
215: Filter filter);
216:
217: /**
218: * FeatureList representing sorted content.
219: * <p>
220: * Available via getFeatureSource():
221: * <ul>
222: * <li>getFeatures().sort( sort )
223: * <li>getFeatures( filter ).sort( sort )
224: * <li>getFeatures( filter ).sort( sort ).sort( sort1 );
225: * </ul>
226: * @param state
227: * @param filter
228: * @param order List<SortBy> used to determine sort order
229: * @return subset of content
230: */
231:
232: //protected abstract FeatureList sorted(ContentState state, Filter filter, List order);
233: /**
234: * FeatureCollection optimized for read-only access.
235: * <p>
236: * Available via getView( filter ):
237: * <ul>
238: * <li>getFeatures().sort( sort )
239: * <li>getFeatures( filter ).sort( sort )
240: * </ul>
241: * <p>
242: * In particular this method of data access is intended for rendering and other high speed
243: * operations; care should be taken to optimize the use of FeatureVisitor.
244: * <p>
245: * @param state
246: * @param filter
247: * @return readonly access
248: */
249:
250: //protected abstract FeatureCollection readonly(ContentState state, Filter filter);
251: }
|