Source Code Cross Referenced for AbstractFeatureInfoResponse.java in  » GIS » GeoServer » org » vfny » geoserver » wms » responses » featureInfo » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoServer » org.vfny.geoserver.wms.responses.featureInfo 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org.  All rights reserved.
002:         * This code is licensed under the GPL 2.0 license, availible at the root
003:         * application directory.
004:         */
005:        package org.vfny.geoserver.wms.responses.featureInfo;
006:
007:        import java.awt.geom.AffineTransform;
008:        import java.awt.geom.NoninvertibleTransformException;
009:        import java.awt.geom.Point2D;
010:        import java.io.IOException;
011:        import java.io.OutputStream;
012:        import java.util.ArrayList;
013:        import java.util.List;
014:        import java.util.logging.Logger;
015:
016:        import org.geotools.coverage.GridSampleDimension;
017:        import org.geotools.coverage.grid.GridCoverage2D;
018:        import org.geotools.data.DataUtilities;
019:        import org.geotools.data.DefaultQuery;
020:        import org.geotools.data.Query;
021:        import org.geotools.factory.CommonFactoryFinder;
022:        import org.geotools.factory.GeoTools;
023:        import org.geotools.feature.AttributeType;
024:        import org.geotools.feature.AttributeTypeFactory;
025:        import org.geotools.feature.FeatureCollection;
026:        import org.geotools.feature.FeatureType;
027:        import org.geotools.feature.FeatureTypeBuilder;
028:        import org.geotools.feature.IllegalAttributeException;
029:        import org.geotools.feature.SchemaException;
030:        import org.geotools.filter.IllegalFilterException;
031:        import org.geotools.geometry.DirectPosition2D;
032:        import org.geotools.geometry.jts.JTS;
033:        import org.geotools.referencing.CRS;
034:        import org.opengis.coverage.PointOutsideCoverageException;
035:        import org.opengis.filter.Filter;
036:        import org.opengis.filter.FilterFactory2;
037:        import org.opengis.geometry.DirectPosition;
038:        import org.opengis.geometry.MismatchedDimensionException;
039:        import org.opengis.referencing.FactoryException;
040:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
041:        import org.opengis.referencing.operation.MathTransform;
042:        import org.opengis.referencing.operation.TransformException;
043:        import org.vfny.geoserver.ServiceException;
044:        import org.vfny.geoserver.global.CoverageInfo;
045:        import org.vfny.geoserver.global.FeatureTypeInfo;
046:        import org.vfny.geoserver.global.GeoServer;
047:        import org.vfny.geoserver.global.MapLayerInfo;
048:        import org.vfny.geoserver.wms.WmsException;
049:        import org.vfny.geoserver.wms.requests.GetFeatureInfoRequest;
050:        import org.vfny.geoserver.wms.requests.GetMapRequest;
051:
052:        import com.vividsolutions.jts.geom.Coordinate;
053:        import com.vividsolutions.jts.geom.Envelope;
054:        import com.vividsolutions.jts.geom.GeometryFactory;
055:        import com.vividsolutions.jts.geom.LinearRing;
056:        import com.vividsolutions.jts.geom.Polygon;
057:
058:        /**
059:         * Abstract class to do the common work of the FeatureInfoResponse subclasses.
060:         * Subclasses should just need to implement writeTo(), to write the actual
061:         * response, the executions are handled here, figuring out where on the map
062:         * the pixel is located.
063:         *
064:         * <p>
065:         * Would be nice to have some greater control over the pixels that are
066:         * selected. Ideally we would be able to detect things like the size of the
067:         * mark, so that users need not click on the exact center, or the exact pixel.
068:         * This is not a big deal for polygons, but is for lines and points.  One
069:         * half solution to make things a bit nicer would be a global parameter to set
070:         * a wider pixel range.
071:         * </p>
072:         *
073:         * @author James Macgill, PSU
074:         * @author Gabriel Roldan, Axios
075:         * @author Chris Holmes, TOPP
076:         * @author Brent Owens, TOPP
077:         */
078:        public abstract class AbstractFeatureInfoResponse extends
079:                GetFeatureInfoDelegate {
080:            /** A logger for this class. */
081:            protected static final Logger LOGGER = org.geotools.util.logging.Logging
082:                    .getLogger("org.vfny.geoserver.responses.wms.featureinfo");
083:
084:            /** The formats supported by this map delegate. */
085:            protected List supportedFormats = null;
086:            protected List results;
087:            protected List metas;
088:
089:            /**
090:             * setted in execute() from the requested output format, it's holded just
091:             * to be sure that method has been called before getContentType() thus
092:             * supporting the workflow contract of the request processing
093:             */
094:            protected String format = null;
095:
096:            /**
097:             * Creates a new GetMapDelegate object.
098:             */
099:
100:            /**
101:             * Autogenerated proxy constructor.
102:             */
103:            public AbstractFeatureInfoResponse() {
104:                super ();
105:            }
106:
107:            /**
108:             * Returns the content encoding for the output data.
109:             *
110:             * <p>
111:             * Note that this reffers to an encoding applied to the response stream
112:             * (such as GZIP or DEFLATE), and not to the MIME response type, wich is
113:             * returned by <code>getContentType()</code>
114:             * </p>
115:             *
116:             * @return <code>null</code> since no special encoding is performed while
117:             *         wrtting to the output stream.
118:             */
119:            public String getContentEncoding() {
120:                return null;
121:            }
122:
123:            /**
124:             * Writes the image to the client.
125:             *
126:             * @param out The output stream to write to.
127:             *
128:             * @throws ServiceException DOCUMENT ME!
129:             * @throws IOException DOCUMENT ME!
130:             */
131:            public abstract void writeTo(OutputStream out)
132:                    throws ServiceException, IOException;
133:
134:            /**
135:             * The formats this delegate supports.
136:             *
137:             * @return The list of the supported formats
138:             */
139:            public List getSupportedFormats() {
140:                return supportedFormats;
141:            }
142:
143:            /**
144:             * DOCUMENT ME!
145:             *
146:             * @param gs app context
147:             *
148:             * @task TODO: implement
149:             */
150:            public void abort(GeoServer gs) {
151:            }
152:
153:            /**
154:             * Gets the content type.  This is set by the request, should only be
155:             * called after execute.  GetMapResponse should handle this though.
156:             *
157:             * @param gs server configuration
158:             *
159:             * @return The mime type that this response will generate.
160:             *
161:             * @throws IllegalStateException if<code>execute()</code> has not been
162:             *         previously called
163:             */
164:            public String getContentType(GeoServer gs) {
165:                if (format == null) {
166:                    throw new IllegalStateException(
167:                            "Content type unknown since execute() has not been called yet");
168:                }
169:
170:                // chain geoserver charset so that multibyte feature info responses
171:                // gets properly encoded, same as getCapabilities responses 
172:                return format + ";charset=" + gs.getCharSet().name();
173:            }
174:
175:            /**
176:             * Performs the execute request using geotools rendering.
177:             *
178:             * @param requestedLayers The information on the types requested.
179:             * @param queries The results of the queries to generate maps with.
180:             * @param x DOCUMENT ME!
181:             * @param y DOCUMENT ME!
182:             *
183:             * @throws WmsException For any problems.
184:             */
185:            protected void execute(MapLayerInfo[] requestedLayers,
186:                    Filter[] filters, int x, int y) throws WmsException {
187:                GetFeatureInfoRequest request = getRequest();
188:                this .format = request.getInfoFormat();
189:
190:                GetMapRequest getMapReq = request.getGetMapRequest();
191:                CoordinateReferenceSystem requestedCRS = getMapReq.getCrs(); // optional, may be null
192:
193:                int width = getMapReq.getWidth();
194:                int height = getMapReq.getHeight();
195:                Envelope bbox = getMapReq.getBbox();
196:
197:                Coordinate upperLeft = pixelToWorld(x - 2, y - 2, bbox, width,
198:                        height);
199:                Coordinate middle = pixelToWorld(x, y, bbox, width, height);
200:                Coordinate lowerRight = pixelToWorld(x + 2, y + 2, bbox, width,
201:                        height);
202:
203:                Coordinate[] coords = new Coordinate[5];
204:                coords[0] = upperLeft;
205:                coords[1] = new Coordinate(lowerRight.x, upperLeft.y);
206:                coords[2] = lowerRight;
207:                coords[3] = new Coordinate(upperLeft.x, lowerRight.y);
208:                coords[4] = coords[0];
209:
210:                GeometryFactory geomFac = new GeometryFactory();
211:                LinearRing boundary = geomFac.createLinearRing(coords); // this needs to be done with each FT so it can be reprojected
212:                FilterFactory2 filterFac = CommonFactoryFinder
213:                        .getFilterFactory2(GeoTools.getDefaultHints());
214:
215:                final int layerCount = requestedLayers.length;
216:                results = new ArrayList(layerCount);
217:                metas = new ArrayList(layerCount);
218:
219:                try {
220:                    for (int i = 0; i < layerCount; i++) {
221:                        if (requestedLayers[i].getType() == org.vfny.geoserver.global.Data.TYPE_VECTOR
222:                                .intValue()) {
223:                            FeatureTypeInfo finfo = requestedLayers[i]
224:                                    .getFeature();
225:
226:                            CoordinateReferenceSystem dataCRS = finfo
227:                                    .getFeatureType().getDefaultGeometry()
228:                                    .getCoordinateSystem();
229:
230:                            // reproject the bounding box
231:                            Polygon pixelRect = geomFac.createPolygon(boundary,
232:                                    null);
233:                            if ((requestedCRS != null)
234:                                    && !CRS.equalsIgnoreMetadata(dataCRS,
235:                                            requestedCRS)) {
236:                                try {
237:                                    MathTransform transform = CRS
238:                                            .findMathTransform(requestedCRS,
239:                                                    dataCRS, true);
240:                                    pixelRect = (Polygon) JTS.transform(
241:                                            pixelRect, transform); // reprojected
242:                                } catch (MismatchedDimensionException e) {
243:                                    LOGGER.severe(e.getLocalizedMessage());
244:                                } catch (TransformException e) {
245:                                    LOGGER.severe(e.getLocalizedMessage());
246:                                } catch (FactoryException e) {
247:                                    LOGGER.severe(e.getLocalizedMessage());
248:                                }
249:                            }
250:
251:                            Filter getFInfoFilter = null;
252:                            try {
253:                                getFInfoFilter = filterFac.intersects(filterFac
254:                                        .property(finfo.getFeatureType()
255:                                                .getDefaultGeometry()
256:                                                .getLocalName()), filterFac
257:                                        .literal(pixelRect));
258:                            } catch (IllegalFilterException e) {
259:                                e.printStackTrace();
260:                                throw new WmsException(null,
261:                                        "Internal error : " + e.getMessage());
262:                            }
263:
264:                            // include the eventual layer definition filter
265:                            if (filters[i] != null) {
266:                                getFInfoFilter = filterFac.and(getFInfoFilter,
267:                                        filters[i]);
268:                            }
269:
270:                            Query q = new DefaultQuery(finfo.getTypeName(),
271:                                    null, getFInfoFilter, request
272:                                            .getFeatureCount(),
273:                                    Query.ALL_NAMES, null);
274:                            FeatureCollection match = finfo.getFeatureSource()
275:                                    .getFeatures(q);
276:
277:                            //this was crashing Gml2FeatureResponseDelegate due to not setting
278:                            //the featureresults, thus not being able of querying the SRS
279:                            //if (match.getCount() > 0) {
280:                            results.add(match);
281:                            metas.add(requestedLayers[i]);
282:
283:                            //}
284:                        } else {
285:                            CoverageInfo cinfo = requestedLayers[i]
286:                                    .getCoverage();
287:                            GridCoverage2D coverage = ((GridCoverage2D) cinfo
288:                                    .getCoverage()).geophysics(true);
289:                            //                    MathTransform mathTrans = coverage.getGridGeometry().getGridToCRS().inverse();
290:                            //                    DirectPosition position = mathTrans.transform(new DirectPosition2D(middle.x, middle.y), null);
291:                            DirectPosition position = new DirectPosition2D(
292:                                    requestedCRS, middle.x, middle.y);
293:                            try {
294:                                double[] pixelValues = coverage.evaluate(
295:                                        position, (double[]) null);
296:                                FeatureCollection pixel = wrapPixelInFeatureCollection(
297:                                        coverage, pixelValues, cinfo.getName());
298:                                metas.add(requestedLayers[i]);
299:                                results.add(pixel);
300:                            } catch (PointOutsideCoverageException e) {
301:                                // it's fine, users might legitimately query point outside, we just don't return anything
302:                            }
303:                        }
304:                    }
305:                } catch (Exception e) {
306:                    throw new WmsException(null, "Internal error occurred", e);
307:                }
308:            }
309:
310:            private FeatureCollection wrapPixelInFeatureCollection(
311:                    GridCoverage2D coverage, double[] pixelValues,
312:                    String coverageName) throws SchemaException,
313:                    IllegalAttributeException {
314:                GridSampleDimension[] sampleDimensions = coverage
315:                        .getSampleDimensions();
316:                AttributeType[] types = new AttributeType[sampleDimensions.length];
317:                FeatureType gridType;
318:                try {
319:                    for (int i = 0; i < types.length; i++) {
320:                        types[i] = AttributeTypeFactory
321:                                .newAttributeType(sampleDimensions[i]
322:                                        .getDescription().toString(),
323:                                        Double.class);
324:                    }
325:                    gridType = FeatureTypeBuilder.newFeatureType(types,
326:                            coverageName);
327:                } catch (Exception e) {
328:                    // sometimes a grid coverage format does not assign unique descriptions to coverages
329:                    for (int i = 0; i < types.length; i++) {
330:                        types[i] = AttributeTypeFactory.newAttributeType(
331:                                "Band " + (i + 1), Double.class);
332:                    }
333:                    gridType = FeatureTypeBuilder.newFeatureType(types,
334:                            coverageName);
335:                }
336:
337:                Double[] values = new Double[pixelValues.length];
338:                for (int i = 0; i < values.length; i++) {
339:                    values[i] = new Double(pixelValues[i]);
340:                }
341:                return DataUtilities.collection(gridType.create(values, ""));
342:            }
343:
344:            /**
345:             * Converts a coordinate expressed on the device space back to real world
346:             * coordinates.  Stolen from LiteRenderer but without the need of a
347:             * Graphics object
348:             *
349:             * @param x horizontal coordinate on device space
350:             * @param y vertical coordinate on device space
351:             * @param map The map extent
352:             * @param width image width
353:             * @param height image height
354:             *
355:             * @return The correspondent real world coordinate
356:             *
357:             * @throws RuntimeException DOCUMENT ME!
358:             */
359:            private Coordinate pixelToWorld(int x, int y, Envelope map,
360:                    int width, int height) {
361:                //set up the affine transform and calculate scale values
362:                AffineTransform at = worldToScreenTransform(map, width, height);
363:
364:                Point2D result = null;
365:
366:                try {
367:                    result = at.inverseTransform(
368:                            new java.awt.geom.Point2D.Double(x, y),
369:                            new java.awt.geom.Point2D.Double());
370:                } catch (NoninvertibleTransformException e) {
371:                    throw new RuntimeException(e);
372:                }
373:
374:                Coordinate c = new Coordinate(result.getX(), result.getY());
375:
376:                return c;
377:            }
378:
379:            /**
380:             * Sets up the affine transform.  Stolen from liteRenderer code.
381:             *
382:             * @param mapExtent the map extent
383:             * @param width the screen size
384:             * @param height DOCUMENT ME!
385:             *
386:             * @return a transform that maps from real world coordinates to the screen
387:             */
388:            private AffineTransform worldToScreenTransform(Envelope mapExtent,
389:                    int width, int height) {
390:                double scaleX = (double) width / mapExtent.getWidth();
391:                double scaleY = (double) height / mapExtent.getHeight();
392:
393:                double tx = -mapExtent.getMinX() * scaleX;
394:                double ty = (mapExtent.getMinY() * scaleY) + height;
395:
396:                AffineTransform at = new AffineTransform(scaleX, 0.0d, 0.0d,
397:                        -scaleY, tx, ty);
398:
399:                return at;
400:            }
401:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.