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;
017:
018: import java.io.IOException;
019: import org.opengis.filter.Filter;
020: import org.geotools.feature.FeatureCollection;
021: import org.geotools.feature.FeatureType;
022: import org.geotools.feature.SchemaException;
023:
024: /**
025: * Represents a Physical Store for FeatureTypes.
026: *
027: * <p>
028: * The source of data for FeatureTypes. Shapefiles, databases tables, etc. are
029: * referenced through this interface.
030: * </p>
031: *
032: * <p>
033: * Summary of our requirements:
034: * </p>
035: *
036: * <ul>
037: * <li>
038: * Provides lookup of available Feature Types
039: * </li>
040: * <li>
041: * Provides access to low-level Readers/Writers API for a feature type
042: * </li>
043: * <li>
044: * Provides access to high-level FeatureSource/Store/Locking API a feature type
045: * </li>
046: * <li>
047: * Handles the conversion of filters into data source specific queries
048: * </li>
049: * <li>
050: * Handles creation of new Feature Types
051: * </li>
052: * <li>
053: * Provides access of Feature Type Schema information
054: * </li>
055: * </ul>
056: *
057: * Suggestions:
058: *
059: * <ul>
060: * <li>GeoAPI - has reduced this to api to the FeatureStore construct
061: * Jody - since we are no longer using the FeatureReader/ReaderWriter in client
062: * code this would not be a bad idea.
063: * </li>
064: * </ul>
065: *
066: * @author Jody Garnett, Refractions Research
067: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/api/src/main/java/org/geotools/data/DataStore.java $
068: * @version $Id: DataStore.java 27585 2007-10-23 13:08:01Z aaime $
069: */
070: public interface DataStore {
071: /**
072: * Creates storage for a new <code>featureType</code>.
073: *
074: * <p>
075: * The provided <code>featureType</code> we be accessable by the typeName
076: * provided by featureType.getTypeName().
077: * </p>
078: *
079: * @param featureType FetureType to add to DataStore
080: *
081: * @throws IOException If featureType cannot be created
082: */
083: void createSchema(FeatureType featureType) throws IOException;
084:
085: /**
086: * Used to force namespace and CS info into a persistent change.
087: * <p>
088: * The provided featureType should completely cover the existing schema.
089: * All attributes should be accounted for and the typeName should match.
090: * </p>
091: * <p>
092: * Suggestions:
093: * </p>
094: * <ul>
095: * <li>Sean - don't do this</li>
096: * <li>Jody - Just allow changes to metadata: CS, namespace, and others</li>
097: * <li>James - Allow change/addition of attribtues</li>
098: * </ul>
099: * @param typeName
100: * @throws IOException
101: */
102: void updateSchema(String typeName, FeatureType featureType)
103: throws IOException;
104:
105: /**
106: * Retrieves a list of of the available FeatureTypes.
107: *
108: * <p>
109: * This is simply a list of the FeatureType names as aquiring the actual
110: * FeatureType schemas may be expensive.
111: * </p>
112: *
113: * <p>
114: * Warning: this list may not be unique - the types may be
115: * in separate namespaces.
116: * </p>
117: *
118: * <p>
119: * If you need to worry about such things please consider the use of
120: * the Catalog and CatalogEntry interface - many DataStores support this.
121: * getTypeNames is really a convience method for a Catalog.iterator() where
122: * the name of each entry is returned.
123: * </p>
124: *
125: * @return typeNames for available FeatureTypes.
126: */
127: String[] getTypeNames() throws IOException;
128:
129: /**
130: * Retrieve FeatureType metadata by <code>typeName</code>.
131: *
132: * <p>
133: * Retrieves the Schema information as a FeatureType object.
134: * </p>
135: *
136: * @param typeName typeName of requested FeatureType
137: *
138: * @return FeatureType for the provided typeName
139: *
140: * @throws IOException If typeName cannot be found
141: */
142: FeatureType getSchema(String typeName) throws IOException;
143:
144: /**
145: * Access a FeatureSource for Query providing a high-level API.
146: * <p>
147: * The provided Query does not need to completely cover the existing
148: * schema for Query.getTypeName(). The result will mostly likely only be
149: * a FeatureSource and probably wont' allow write access by the
150: * FeatureStore method.
151: * </p>
152: * <p>
153: * By using Query we allow support for reprojection, in addition
154: * to overriding the CoordinateSystem used by the native FeatureType.
155: * </p>
156: * <p>
157: * We may wish to limit this method to only support Queries using
158: * Filter.EXCLUDE.
159: * </p>
160: * <p>
161: * Update - GeoServer has an elegatent implementation of this functionality
162: * that we could steal. GeoServerFeatureSource, GeoServerFeatureStore and
163: * GeoServerFeatureLocking serve as a working prototype.
164: * </p>
165: * @param query Query.getTypeName() locates FeatureType being viewed
166: *
167: * @return FeatureSource providing operations for featureType
168: * @throws IOException If FeatureSource is not available
169: * @throws SchemaException If fetureType is not covered by existing schema
170: */
171: FeatureSource getView(Query query) throws IOException,
172: SchemaException;
173:
174: /**
175: * Access a FeatureSource for typeName providing a high-level API.
176: *
177: * <p>
178: * The resulting FeatureSource may implment more functionality:
179: * </p>
180: * <pre><code>
181: *
182: * FeatureSource fsource = dataStore.getFeatureSource( "roads" );
183: * FeatureStore fstore = null;
184: * if( fsource instanceof FeatureLocking ){
185: * fstore = (FeatureStore) fs;
186: * }
187: * else {
188: * System.out.println("We do not have write access to roads");
189: * }
190: * </code>
191: * </pre>
192: *
193: * @param typeName
194: *
195: * @return FeatureSource (or subclass) providing operations for typeName
196: */
197: FeatureSource getFeatureSource(String typeName) throws IOException;
198:
199: /**
200: * Access a FeatureReader providing access to Feature information.
201: *
202: * <p>
203: * <b>Filter</b> is used as a low-level indication of constraints.
204: * (Implementations may resort to using a FilteredFeatureReader, or
205: * provide their own optimizations)
206: * </p>
207: *
208: * <p>
209: * <b>FeatureType</b> provides a template for the returned FeatureReader
210: * </p>
211: *
212: * <ul>
213: * <li>
214: * featureType.getTypeName(): used by JDBC as the table reference to query
215: * against. Shapefile reader may need to store a lookup to the required
216: * filename.
217: * </li>
218: * <li>
219: * featureType.getAttributeTypes(): describes the requested content. This
220: * may be a subset of the complete FeatureType defined by the DataStore.
221: * </li>
222: * <li>
223: * getType.getNamespace(): describes the requested namespace for the
224: * results (may be different then the one used internally)
225: * </li>
226: * </ul>
227: *
228: * <p>
229: * <b>Transaction</b> to externalize DataStore state on a per Transaction
230: * basis. The most common example is a JDBC datastore saving a Connection
231: * for use across several FeatureReader requests. Similarly a Shapefile
232: * reader may wish to redirect FeatureReader requests to a alternate
233: * filename over the course of a Transaction.
234: * </p>
235: *
236: * <p>
237: * <b>Notes For Implementing DataStore</b>
238: * </p>
239: *
240: * <p>
241: * Subclasses may need to retrieve additional attributes, beyond those
242: * requested by featureType.getAttributeTypes(), in order to correctly
243: * apply the <code>filter</code>.<br>
244: * These Additional <b>attribtues</b> should be not be returned by
245: * FeatureReader. Subclasses may use ReTypeFeatureReader to aid in
246: * acomplishing this.
247: * </p>
248: * <p>
249: * Helper classes for implementing a FeatureReader (in order):
250: * </p>
251: * <ul>
252: * <li>
253: * DefaultFeatureReader
254: * - basic support for creating a FeatureReader for an AttributeReader
255: * </li>
256: * <li>
257: * FilteringFeatureReader
258: * - filtering support
259: * </li>
260: * <li>
261: * DiffFeatureReader
262: * - In-Process Transaction Support (see TransactionStateDiff)
263: * </li>
264: * <li>
265: * ReTypeFeatureReader
266: * - Feature Type schema manipulation of namesspace and attribute type subsets
267: * </li>
268: * <li>
269: * EmptyFeatureReader
270: * - provides no content for Filter.EXCLUDE optimizations
271: * </li>
272: * </ul>
273: * <p>
274: * Sample use (not optimized):
275: * </p>
276: * <pre><code>
277: * if (filter == Filter.EXCLUDE) {
278: * return new EmptyFeatureReader(featureType);
279: * }
280: *
281: * String typeName = featureType.getTypeName();
282: * FeatureType schema = getSchema( typeName );
283: * FeatureReader reader = new DefaultFeatureReader( getAttributeReaders(), schema );
284: *
285: * if (filter != Filter.INCLUDE) {
286: * reader = new FilteringFeatureReader(reader, filter);
287: * }
288: *
289: * if (transaction != Transaction.AUTO_COMMIT) {
290: * Map diff = state(transaction).diff(typeName);
291: * reader = new DiffFeatureReader(reader, diff);
292: * }
293: *
294: * if (!featureType.equals(reader.getFeatureType())) {
295: * reader = new ReTypeFeatureReader(reader, featureType);
296: * }
297: * return reader
298: * </code></pre>
299: * <p>
300: * Locking support does not need to be provided for FeatureReaders.
301: * </p>
302: *
303: * @param query Requested form of the returned Features and the filter used
304: * to constraints the results
305: * @param transaction Transaction this query operates against
306: *
307: * @return FeatureReader Allows Sequential Processing of featureType
308: */
309: FeatureReader getFeatureReader(Query query, Transaction transaction)
310: throws IOException;
311:
312: /**
313: * Access FeatureWriter for modification of existing DataStore contents.
314: *
315: * <p>
316: * To limit FeatureWriter to the FeatureTypes defined by this DataStore,
317: * typeName is used to indicate FeatureType. The resulting
318: * feature writer will allow modifications against the
319: * same FeatureType provided by getSchema( typeName )
320: * </p>
321: *
322: * <p>
323: * The FeatureWriter will provide access to the existing contents of the
324: * FeatureType referenced by typeName. The provided filter will be used
325: * to skip over Features as required.
326: * </p>
327: *
328: * <b>Notes For Implementing DataStore</b>
329: * </p>
330: *
331: * <p>
332: * The returned FeatureWriter <b>does not</b> support the addition of new
333: * Features to FeatureType (it would need to police your modifications to
334: * agree with <code>filer</code>). As such it will return
335: * <code>false</code> for getNext() when it reaches the end of the Query
336: * and NoSuchElementException when next() is called.
337: * </p>
338: *
339: * <p>
340: * Helper classes for implementing a FeatureWriter (in order):
341: * </p>
342: * <li>
343: * InProcessLockingManager.checkedWriter( writer )
344: * - provides a check against locks before allowing modification
345: *
346: * <li>
347: * FilteringFeatureWriter
348: * - filtering support for FeatureWriter (does not allow new content)
349: * </li>
350: * <li>
351: * DiffFeatureWriter
352: * - In-Process Transaction Support (see TransactionStateDiff)
353: * </li>
354: * <li>
355: * EmptyFeatureWriter
356: * - provides no content for Filter.EXCLUDE optimizations
357: * </li>
358: * </ul>
359: *
360: * @param typeName Indicates featureType to be modified
361: * @param filter constraints used to limit the modification
362: * @param transaction Transaction this query operates against
363: *
364: * @return FeatureWriter Allows Sequential Modification of featureType
365: */
366: FeatureWriter getFeatureWriter(String typeName, Filter filter,
367: Transaction transaction) throws IOException;
368:
369: /**
370: * Access FeatureWriter for modification of the DataStore typeName.
371: *
372: * <p>
373: * FeatureWriters will need to be limited to the FeatureTypes defined by
374: * the DataStore, the easiest way to express this limitation is to the
375: * FeatureType by a provided typeName.
376: * </p>
377: *
378: * <p>
379: * The returned FeatureWriter will return <code>false</code> for getNext()
380: * when it reaches the end of the Query.
381: * </p>
382: *
383: * @param typeName Indicates featureType to be modified
384: * @param transaction Transaction to operates against
385: *
386: * @return FeatureReader Allows Sequential Processing of featureType
387: */
388: FeatureWriter getFeatureWriter(String typeName,
389: Transaction transaction) throws IOException;
390:
391: /**
392: * Aquire a FeatureWriter for adding new content to a FeatureType.
393: *
394: * <p>
395: * This FeatureWriter will return <code>false</code> for hasNext(), however
396: * next() may be used to aquire new Features that may be writen out to add
397: * new content.
398: * </p>
399: *
400: * @param typeName Indicates featureType to be modified
401: * @param transaction Transaction to operates against
402: *
403: * @return FeatureWriter that may only be used to append new content
404: *
405: * @throws IOException
406: */
407: FeatureWriter getFeatureWriterAppend(String typeName,
408: Transaction transaction) throws IOException;
409:
410: /**
411: * Retrieve a per featureID based locking service from this DataStore.
412: *
413: * <p>
414: * It is common to return an instanceof InProcessLockingManager for
415: * DataStores that do not provide native locking.
416: * </p>
417: *
418: * <p>
419: * AbstractFeatureLocking makes use of this service to provide locking
420: * support. You are not limitied by this implementation and may simply
421: * return <code>null</code> for this value.
422: * </p>
423: *
424: * @return DataStores may return <code>null</code>, if the handling locking
425: * in another fashion.
426: */
427: LockingManager getLockingManager();
428:
429: /**
430: * Disposes of this data store and releases any resource that it is using.
431: * <p>
432: * A <code>DataStore</code> cannot be used after <code>dispose</code> has
433: * been called, neither can any data access object it helped create, such
434: * as {@link FeatureReader}, {@link FeatureSource} or {@link FeatureCollection}.
435: * <p>
436: * This operation can be called more than once without side effects.
437: * <p>
438: * There is no thread safety assurance associated with this method. For example,
439: * client code will have to make sure this method is not called while retrieving/saving data
440: * from/to the storage, or be prepared for the consequences.
441: */
442: void dispose();
443: }
|