001: /*
002: * uDig - User Friendly Desktop Internet GIS client
003: * http://udig.refractions.net
004: * (C) 2004, Refractions Research Inc.
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: */
017: package net.refractions.udig.catalog.internal.postgis;
018:
019: import java.io.IOException;
020: import java.net.MalformedURLException;
021: import java.net.URI;
022: import java.net.URL;
023: import java.sql.Connection;
024: import java.sql.SQLException;
025:
026: import net.refractions.udig.catalog.CatalogPlugin;
027: import net.refractions.udig.catalog.IGeoResource;
028: import net.refractions.udig.catalog.IGeoResourceInfo;
029: import net.refractions.udig.catalog.IService;
030: import net.refractions.udig.catalog.postgis.internal.Messages;
031: import net.refractions.udig.core.internal.CorePlugin;
032: import net.refractions.udig.ui.graphics.Glyph;
033:
034: import org.eclipse.core.runtime.IProgressMonitor;
035: import org.eclipse.core.runtime.IStatus;
036: import org.geotools.data.DataSourceException;
037: import org.geotools.data.FeatureReader;
038: import org.geotools.data.FeatureSource;
039: import org.geotools.data.FeatureStore;
040: import org.geotools.feature.Feature;
041: import org.geotools.feature.FeatureType;
042: import org.geotools.feature.GeometryAttributeType;
043: import org.geotools.geometry.jts.ReferencedEnvelope;
044: import org.geotools.referencing.CRS;
045: import org.geotools.referencing.crs.DefaultGeographicCRS;
046: import org.geotools.resources.CRSUtilities;
047: import org.opengis.referencing.crs.CoordinateReferenceSystem;
048:
049: import com.vividsolutions.jts.geom.Envelope;
050:
051: /**
052: * Provides ...TODO summary sentence
053: * <p>
054: * TODO Description
055: * </p>
056: *
057: * @author David Zwiers, Refractions Research
058: * @since 0.6
059: */
060: public class PostGISGeoResource extends IGeoResource {
061: PostGISServiceImpl parent;
062: String typename = null;
063: private volatile Status status;
064: private volatile Throwable message;
065: private URL identifier;
066:
067: private PostGISGeoResource() {/* not for use */
068: }
069:
070: /**
071: * Construct <code>PostGISGeoResource</code>.
072: *
073: * @param parent
074: * @param typename
075: */
076: public PostGISGeoResource(PostGISServiceImpl parent, String typename) {
077: this .parent = parent;
078: this .typename = typename;
079: try {
080: identifier = new URL(null, parent.getIdentifier()
081: .toString()
082: + "#" + typename, CorePlugin.RELAXED_HANDLER); //$NON-NLS-1$
083: } catch (MalformedURLException e) {
084: identifier = parent.getIdentifier();
085: }
086: }
087:
088: public URL getIdentifier() {
089: return identifier;
090: }
091:
092: /*
093: * @see net.refractions.udig.catalog.IGeoResource#getStatus()
094: */
095: public Status getStatus() {
096: if (status != null)
097: return status;
098: return parent.getStatus();
099: }
100:
101: /*
102: * @see net.refractions.udig.catalog.IGeoResource#getStatusMessage()
103: */
104: public Throwable getMessage() {
105: if (message != null)
106: return message;
107: return parent.getMessage();
108: }
109:
110: /*
111: * Required adaptions: <ul> <li>IGeoResourceInfo.class <li>IService.class </ul>
112: *
113: * @see net.refractions.udig.catalog.IResolve#resolve(java.lang.Class,
114: * org.eclipse.core.runtime.IProgressMonitor)
115: */
116: public <T> T resolve(Class<T> adaptee, IProgressMonitor monitor)
117: throws IOException {
118: if (adaptee == null)
119: return null;
120: if (adaptee.isAssignableFrom(IGeoResourceInfo.class))
121: return adaptee.cast(getInfo(monitor));
122: if (adaptee.isAssignableFrom(IGeoResource.class))
123: return adaptee.cast(this );
124: if (adaptee.isAssignableFrom(FeatureStore.class)) {
125: FeatureSource fs = parent.getDS()
126: .getFeatureSource(typename);
127: if (fs instanceof FeatureStore)
128: return adaptee.cast(fs);
129: if (adaptee.isAssignableFrom(FeatureSource.class))
130: return adaptee.cast(parent.getDS().getFeatureSource(
131: typename));
132: }
133: if (adaptee.isAssignableFrom(Connection.class)) {
134: return parent.resolve(adaptee, monitor);
135: }
136:
137: return super .resolve(adaptee, monitor);
138: }
139:
140: public IService service(IProgressMonitor monitor)
141: throws IOException {
142: return parent;
143: }
144:
145: /*
146: * @see net.refractions.udig.catalog.IResolve#canResolve(java.lang.Class)
147: */
148: public <T> boolean canResolve(Class<T> adaptee) {
149: if (adaptee == null)
150: return false;
151: return (adaptee.isAssignableFrom(IGeoResourceInfo.class)
152: || adaptee.isAssignableFrom(FeatureStore.class)
153: || adaptee.isAssignableFrom(FeatureSource.class) || adaptee
154: .isAssignableFrom(IService.class))
155: || adaptee.isAssignableFrom(Connection.class)
156: || super .canResolve(adaptee);
157: }
158:
159: private volatile IGeoResourceInfo info;
160:
161: public IGeoResourceInfo getInfo(IProgressMonitor monitor)
162: throws IOException {
163: if (info == null && getStatus() != Status.BROKEN) {
164: parent.rLock.lock();
165: try {
166: if (info == null) {
167: info = new PostGISResourceInfo();
168: }
169: } finally {
170: parent.rLock.unlock();
171: }
172: }
173: return info;
174: }
175:
176: class PostGISResourceInfo extends IGeoResourceInfo {
177:
178: private FeatureType ft = null;
179:
180: PostGISResourceInfo() throws IOException {
181:
182: try {
183: ft = parent.getDS().getSchema(typename);
184: } catch (DataSourceException e) {
185: if (e.getMessage().contains("permission")) { //$NON-NLS-1$
186: status = Status.RESTRICTED_ACCESS;
187: } else {
188: status = Status.BROKEN;
189: }
190: message = e;
191: PostgisPlugin
192: .log(
193: "Unable to retrieve FeatureType schema for type '" + typename + "'.", e); //$NON-NLS-1$ //$NON-NLS-2$
194: keywords = new String[] { "postgis", //$NON-NLS-1$
195: typename };
196: return;
197: }
198:
199: keywords = new String[] { "postgis", //$NON-NLS-1$
200: typename, ft.getNamespace().toString() };
201:
202: try {
203: FeatureSource source = parent.getDS().getFeatureSource(
204: typename);
205: Envelope temp = parent.getDS().getEnvelope(typename);
206: System.out.println(typename);
207: GeometryAttributeType defGeom = source.getSchema()
208: .getDefaultGeometry();
209: if (defGeom == null) { //non-geom table!
210: bounds = new ReferencedEnvelope(new Envelope(),
211: null);
212: CatalogPlugin
213: .log(
214: "FeatureType '" + typename + "' does not have a geometry", null); //$NON-NLS-1$ //$NON-NLS-2$
215: return;
216: }
217: CoordinateReferenceSystem crs = defGeom
218: .getCoordinateSystem();
219: if (temp instanceof ReferencedEnvelope) {
220: bounds = (ReferencedEnvelope) temp;
221: } else {
222: if (temp != null) {
223: if (crs == null) {
224: crs = CRS.decode("EPSG:4326"); //$NON-NLS-1$
225: }
226: bounds = new ReferencedEnvelope(temp, crs);
227: }
228: }
229: if (bounds == null) {
230:
231: // try getting an envelope out of the crs
232: org.opengis.spatialschema.geometry.Envelope envelope = CRSUtilities
233: .getEnvelope(crs);
234:
235: if (envelope != null) {
236: bounds = new ReferencedEnvelope(new Envelope(
237: envelope.getLowerCorner()
238: .getOrdinate(0), envelope
239: .getLowerCorner()
240: .getOrdinate(1), envelope
241: .getUpperCorner()
242: .getOrdinate(0), envelope
243: .getUpperCorner()
244: .getOrdinate(1)), crs);
245: } else {
246: // TODO: perhaps access a preference which indicates
247: // whether to do a full table scan
248: // bounds = new ReferencedEnvelope(new Envelope(),crs);
249: // as a last resort do the full scan
250: bounds = new ReferencedEnvelope(new Envelope(),
251: crs);
252: for (FeatureReader iter = source.getFeatures()
253: .reader(); iter.hasNext();) {
254: Feature element = iter.next();
255: if (bounds.isNull())
256: bounds.init(element.getBounds());
257: else
258: bounds.expandToInclude(element
259: .getBounds());
260: }
261: }
262: }
263: } catch (DataSourceException e) {
264: PostgisPlugin
265: .log(
266: "Exception while generating PostGISGeoResource.", e); //$NON-NLS-1$
267: } catch (Exception e) {
268: CatalogPlugin
269: .getDefault()
270: .getLog()
271: .log(
272: new org.eclipse.core.runtime.Status(
273: IStatus.WARNING,
274: "net.refractions.udig.catalog", 0, Messages.PostGISGeoResource_error_layer_bounds, e)); //$NON-NLS-1$
275: bounds = new ReferencedEnvelope(new Envelope(), null);
276: }
277:
278: icon = Glyph.icon(ft);
279:
280: }
281:
282: public CoordinateReferenceSystem getCRS() {
283: if (status == Status.BROKEN
284: || status == Status.RESTRICTED_ACCESS)
285: return DefaultGeographicCRS.WGS84;
286:
287: GeometryAttributeType defGeom = ft.getDefaultGeometry();
288: if (defGeom == null)
289: return null;
290: return defGeom.getCoordinateSystem();
291: }
292:
293: public String getName() {
294: return typename;
295: }
296:
297: public URI getSchema() {
298: if (status == Status.BROKEN
299: || status == Status.RESTRICTED_ACCESS)
300: return null;
301: return ft.getNamespace();
302: }
303:
304: public String getTitle() {
305: return typename;
306: }
307: }
308:
309: }
|