Source Code Cross Referenced for DefaultGetFeatureInfoHandler.java in  » GIS » deegree » org » deegree » ogcwebservices » wms » 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 » deegree » org.deegree.ogcwebservices.wms 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/ogcwebservices/wms/DefaultGetFeatureInfoHandler.java $
0002:        /*----------------    FILE HEADER  ------------------------------------------
0003:
0004:         This file is part of deegree.
0005:         Copyright (C) 2001-2008 by:
0006:         EXSE, Department of Geography, University of Bonn
0007:         http://www.giub.uni-bonn.de/deegree/
0008:         lat/lon GmbH
0009:         http://www.lat-lon.de
0010:
0011:         This library is free software; you can redistribute it and/or
0012:         modify it under the terms of the GNU Lesser General Public
0013:         License as published by the Free Software Foundation; either
0014:         version 2.1 of the License, or (at your option) any later version.
0015:
0016:         This library is distributed in the hope that it will be useful,
0017:         but WITHOUT ANY WARRANTY; without even the implied warranty of
0018:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019:         Lesser General Public License for more details.
0020:
0021:         You should have received a copy of the GNU Lesser General Public
0022:         License along with this library; if not, write to the Free Software
0023:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0024:
0025:         Contact:
0026:
0027:         Andreas Poth
0028:         lat/lon GmbH
0029:         Aennchenstr. 19
0030:         53177 Bonn
0031:         Germany
0032:         E-Mail: poth@lat-lon.de
0033:
0034:         Prof. Dr. Klaus Greve
0035:         Department of Geography
0036:         University of Bonn
0037:         Meckenheimer Allee 166
0038:         53115 Bonn
0039:         Germany
0040:         E-Mail: greve@giub.uni-bonn.de
0041:
0042:        
0043:         ---------------------------------------------------------------------------*/
0044:        package org.deegree.ogcwebservices.wms;
0045:
0046:        import java.awt.Color;
0047:        import java.awt.image.BufferedImage;
0048:        import java.io.ByteArrayInputStream;
0049:        import java.io.InputStreamReader;
0050:        import java.io.Reader;
0051:        import java.io.StringReader;
0052:        import java.net.URI;
0053:        import java.net.URL;
0054:        import java.util.ArrayList;
0055:        import java.util.Arrays;
0056:        import java.util.Iterator;
0057:        import java.util.List;
0058:        import java.util.Map;
0059:        import java.util.concurrent.Callable;
0060:        import java.util.concurrent.CancellationException;
0061:
0062:        import org.deegree.datatypes.QualifiedName;
0063:        import org.deegree.datatypes.Types;
0064:        import org.deegree.datatypes.UnknownTypeException;
0065:        import org.deegree.datatypes.values.Values;
0066:        import org.deegree.framework.concurrent.ExecutionFinishedEvent;
0067:        import org.deegree.framework.concurrent.ExecutionFinishedListener;
0068:        import org.deegree.framework.concurrent.Executor;
0069:        import org.deegree.framework.log.ILogger;
0070:        import org.deegree.framework.log.LoggerFactory;
0071:        import org.deegree.framework.util.CharsetUtils;
0072:        import org.deegree.framework.util.IDGenerator;
0073:        import org.deegree.framework.util.MapUtils;
0074:        import org.deegree.framework.util.NetWorker;
0075:        import org.deegree.framework.xml.NamespaceContext;
0076:        import org.deegree.framework.xml.XMLFragment;
0077:        import org.deegree.framework.xml.XMLTools;
0078:        import org.deegree.framework.xml.XSLTDocument;
0079:        import org.deegree.graphics.transformation.GeoTransform;
0080:        import org.deegree.graphics.transformation.WorldToScreenTransform;
0081:        import org.deegree.i18n.Messages;
0082:        import org.deegree.model.coverage.grid.ImageGridCoverage;
0083:        import org.deegree.model.crs.CRSFactory;
0084:        import org.deegree.model.crs.CoordinateSystem;
0085:        import org.deegree.model.crs.GeoTransformer;
0086:        import org.deegree.model.feature.Feature;
0087:        import org.deegree.model.feature.FeatureCollection;
0088:        import org.deegree.model.feature.FeatureFactory;
0089:        import org.deegree.model.feature.FeatureProperty;
0090:        import org.deegree.model.feature.GMLFeatureCollectionDocument;
0091:        import org.deegree.model.feature.schema.FeatureType;
0092:        import org.deegree.model.feature.schema.PropertyType;
0093:        import org.deegree.model.filterencoding.ComplexFilter;
0094:        import org.deegree.model.filterencoding.FeatureFilter;
0095:        import org.deegree.model.filterencoding.FeatureId;
0096:        import org.deegree.model.filterencoding.Filter;
0097:        import org.deegree.model.spatialschema.Envelope;
0098:        import org.deegree.model.spatialschema.GMLGeometryAdapter;
0099:        import org.deegree.model.spatialschema.Geometry;
0100:        import org.deegree.model.spatialschema.GeometryFactory;
0101:        import org.deegree.ogcbase.CommonNamespaces;
0102:        import org.deegree.ogcbase.InvalidSRSException;
0103:        import org.deegree.ogcbase.PropertyPath;
0104:        import org.deegree.ogcwebservices.OGCWebService;
0105:        import org.deegree.ogcwebservices.OGCWebServiceException;
0106:        import org.deegree.ogcwebservices.OGCWebServiceRequest;
0107:        import org.deegree.ogcwebservices.wcs.getcoverage.ResultCoverage;
0108:        import org.deegree.ogcwebservices.wfs.WFService;
0109:        import org.deegree.ogcwebservices.wfs.capabilities.WFSCapabilities;
0110:        import org.deegree.ogcwebservices.wfs.capabilities.WFSFeatureType;
0111:        import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
0112:        import org.deegree.ogcwebservices.wfs.operation.GetFeature;
0113:        import org.deegree.ogcwebservices.wfs.operation.Query;
0114:        import org.deegree.ogcwebservices.wms.capabilities.Layer;
0115:        import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
0116:        import org.deegree.ogcwebservices.wms.configuration.LocalWFSDataSource;
0117:        import org.deegree.ogcwebservices.wms.configuration.RemoteWMSDataSource;
0118:        import org.deegree.ogcwebservices.wms.configuration.WMSConfigurationType;
0119:        import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo;
0120:        import org.deegree.ogcwebservices.wms.operation.GetFeatureInfoResult;
0121:        import org.deegree.ogcwebservices.wms.operation.GetMap;
0122:        import org.deegree.ogcwebservices.wms.operation.WMSProtocolFactory;
0123:        import org.deegree.processing.raster.converter.Image2RawData;
0124:        import org.w3c.dom.Document;
0125:
0126:        /**
0127:         * 
0128:         * 
0129:         * 
0130:         * @version $Revision: 9697 $
0131:         * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
0132:         * @author last edited by: $Author: aschmitz $
0133:         * 
0134:         * @version 1.0. $Revision: 9697 $, $Date: 2008-01-23 03:19:46 -0800 (Wed, 23 Jan 2008) $
0135:         * 
0136:         */
0137:        class DefaultGetFeatureInfoHandler implements  GetFeatureInfoHandler,
0138:                ExecutionFinishedListener<Object[]> {
0139:
0140:            protected static final ILogger LOG = LoggerFactory
0141:                    .getLogger(DefaultGetFeatureInfoHandler.class);
0142:
0143:            private static final double DEFAULT_PIXEL_SIZE = 0.00028;
0144:
0145:            protected GetFeatureInfo request = null;
0146:
0147:            protected GetMap getMapRequest = null;
0148:
0149:            protected WMSConfigurationType configuration = null;
0150:
0151:            // collects the reponse for each layer
0152:            private Object[] featCol = null;
0153:
0154:            // scale of the map
0155:            protected double scale = 0;
0156:
0157:            // holds the number of request services that have responsed
0158:            private int count = 0;
0159:
0160:            // CRS of the request
0161:            protected CoordinateSystem reqCRS = null;
0162:
0163:            protected static final QualifiedName VALUE = new QualifiedName(
0164:                    "value");
0165:
0166:            /**
0167:             * Creates a new GetMapHandler object.
0168:             * 
0169:             * @param capabilities
0170:             * @param request
0171:             *            request to perform
0172:             * @throws OGCWebServiceException
0173:             */
0174:            public DefaultGetFeatureInfoHandler(
0175:                    WMSConfigurationType capabilities, GetFeatureInfo request)
0176:                    throws OGCWebServiceException {
0177:
0178:                this .request = request;
0179:                this .configuration = capabilities;
0180:                getMapRequest = request.getGetMapRequestCopy();
0181:                try {
0182:                    reqCRS = CRSFactory.create(getMapRequest.getSrs());
0183:                    if (reqCRS == null) {
0184:                        throw new InvalidSRSException(Messages.getMessage(
0185:                                "WMS_UNKNOWN_CRS", getMapRequest.getSrs()));
0186:                    }
0187:                } catch (Exception e) {
0188:                    throw new InvalidSRSException(Messages.getMessage(
0189:                            "WMS_UNKNOWN_CRS", getMapRequest.getSrs()));
0190:                }
0191:                try {
0192:                    Envelope bbox = getMapRequest.getBoundingBox();
0193:                    scale = MapUtils.calcScale(getMapRequest.getWidth(),
0194:                            getMapRequest.getHeight(), bbox, reqCRS,
0195:                            DEFAULT_PIXEL_SIZE);
0196:                } catch (Exception e) {
0197:                    LOG.logDebug(e.getLocalizedMessage(), e);
0198:                    throw new OGCWebServiceException(Messages.getMessage(
0199:                            "WMS_SCALECALC", e));
0200:                }
0201:
0202:            }
0203:
0204:            /**
0205:             * increases the counter variable that holds the number of services that has sent a response.
0206:             * All data are available if the counter value equals the number of requested layers.
0207:             */
0208:            protected synchronized void increaseCounter() {
0209:                count++;
0210:            }
0211:
0212:            /**
0213:             * performs a GetFeatureInfo request and retruns the result encapsulated within a
0214:             * <tt>WMSFeatureInfoResponse</tt> object.
0215:             * <p>
0216:             * The method throws an WebServiceException that only shall be thrown if an fatal error occurs
0217:             * that makes it imposible to return a result. If something wents wrong performing the request
0218:             * (none fatal error) The exception shall be encapsulated within the response object to be
0219:             * returned to the client as requested (GetFeatureInfo-Request EXCEPTION-Parameter).
0220:             * 
0221:             * <p>
0222:             * All sublayers of the queried layer will be added automatically. Non-queryable sublayers are
0223:             * then ignored in the response.
0224:             * </p>
0225:             * 
0226:             * @return response to the GetFeatureInfo response
0227:             */
0228:            public GetFeatureInfoResult performGetFeatureInfo()
0229:                    throws OGCWebServiceException {
0230:
0231:                String[] qlayers = request.getQueryLayers();
0232:
0233:                List<Layer> allLayers = new ArrayList<Layer>();
0234:
0235:                // here, the explicitly queried layers are checked for being queryable and known
0236:                for (int i = 0; i < qlayers.length; i++) {
0237:                    Layer layer = configuration.getLayer(qlayers[i]);
0238:
0239:                    if (layer == null) {
0240:                        throw new LayerNotDefinedException(Messages.getMessage(
0241:                                "WMS_UNKNOWNLAYER", qlayers[i]));
0242:                    }
0243:                    if (!layer.isQueryable()) {
0244:                        throw new LayerNotQueryableException(Messages
0245:                                .getMessage("WMS_LAYER_NOT_QUERYABLE",
0246:                                        qlayers[i]));
0247:                    }
0248:                    if (!layer.isSrsSupported(getMapRequest.getSrs())) {
0249:                        throw new InvalidSRSException(Messages.getMessage(
0250:                                "WMS_UNKNOWN_CRS_FOR_LAYER", getMapRequest
0251:                                        .getSrs(), qlayers[i]));
0252:                    }
0253:
0254:                    allLayers.add(layer);
0255:
0256:                    // sublayers are added WITHOUT being checked for being queryable
0257:                    // This is desirable for example in the following scenario:
0258:                    // Suppose one queryable layer contains a lot of other layers,
0259:                    // that are mostly queryable. Then you can query all of those layers
0260:                    // at once by just querying the enclosing layer (the unqueryable
0261:                    // sublayers are ignored).
0262:                    allLayers.addAll(Arrays.asList(layer.getLayer()));
0263:                }
0264:
0265:                Layer[] layerList = allLayers.toArray(new Layer[allLayers
0266:                        .size()]);
0267:
0268:                // there must be one feature collection for each requested layer
0269:                int cnt = countNumberOfQueryableDataSources(layerList);
0270:                featCol = new Object[cnt];
0271:
0272:                // invokes the data supplyer for each layer in an independ thread
0273:                int kk = 0;
0274:                for (int i = 0; i < layerList.length; i++) {
0275:                    if (validate(layerList[i])) {
0276:                        AbstractDataSource datasource[] = layerList[i]
0277:                                .getDataSource();
0278:                        for (int j = 0; j < datasource.length; j++) {
0279:                            if (datasource[j].isQueryable()
0280:                                    && isValidArea(datasource[j].getValidArea())) {
0281:                                ServiceInvoker si = new ServiceInvoker(
0282:                                        layerList[i], datasource[j], kk++);
0283:                                ServiceInvokerTask task = new ServiceInvokerTask(
0284:                                        si);
0285:                                Executor.getInstance().performAsynchronously(
0286:                                        task, this );
0287:                            }
0288:                        }
0289:                    } else {
0290:                        // set feature collection to null if no data are available for the requested
0291:                        // area and/or scale. This will cause this index position will be ignored
0292:                        // when creating the final result
0293:                        featCol[kk++] = null;
0294:                        increaseCounter();
0295:                    }
0296:                }
0297:
0298:                // waits until the requested layers are available as <tt>DisplayElements</tt>
0299:                // or the time limit has been reached.
0300:                // TODO
0301:                // substitue by an event based approach
0302:                try {
0303:                    waitForFinish();
0304:                } catch (Exception e) {
0305:                    return createExceptionResponse(e);
0306:                }
0307:
0308:                GetFeatureInfoResult res = createFeatureInfoResponse();
0309:
0310:                return res;
0311:            }
0312:
0313:            /**
0314:             * returns the number of datasources assigned to the queried layers that are queryable
0315:             * 
0316:             * @param layerList
0317:             * @return the number
0318:             */
0319:            private int countNumberOfQueryableDataSources(Layer[] layerList) {
0320:                int cnt = 0;
0321:                for (int i = 0; i < layerList.length; i++) {
0322:                    AbstractDataSource[] ds = layerList[i].getDataSource();
0323:                    for (int j = 0; j < ds.length; j++) {
0324:                        if (ds[j].isQueryable()
0325:                                && isValidArea(ds[j].getValidArea())) {
0326:                            cnt++;
0327:                        }
0328:                    }
0329:                }
0330:                return cnt;
0331:            }
0332:
0333:            /**
0334:             * returns true if the requested boundingbox intersects with the valid area of a datasource
0335:             * 
0336:             * @param validArea
0337:             */
0338:            private boolean isValidArea(Geometry validArea) {
0339:
0340:                if (validArea != null) {
0341:                    try {
0342:                        Envelope env = request.getGetMapRequestCopy()
0343:                                .getBoundingBox();
0344:                        Geometry geom = GeometryFactory.createSurface(env,
0345:                                reqCRS);
0346:                        if (!reqCRS.getIdentifier()
0347:                                .equals(
0348:                                        validArea.getCoordinateSystem()
0349:                                                .getIdentifier())) {
0350:                            // if requested CRS is not identical to the CRS of the valid area
0351:                            // a transformation must be performed before intersection can
0352:                            // be checked
0353:                            GeoTransformer gt = new GeoTransformer(validArea
0354:                                    .getCoordinateSystem());
0355:                            geom = gt.transform(geom);
0356:                        }
0357:                        return geom.intersects(validArea);
0358:                    } catch (Exception e) {
0359:                        // should never happen
0360:                        LOG.logError("Could not validate WMS datasource area",
0361:                                e);
0362:                    }
0363:                }
0364:                return true;
0365:            }
0366:
0367:            /**
0368:             * validates if the requested layer matches the conditions of the request if not a
0369:             * <tt>WebServiceException</tt> will be thrown. If the layer matches the request, but isn't
0370:             * able to deviever data for the requested area and/or scale false will be returned. If the
0371:             * layer matches the request and contains data for the requested area and/or scale true will be
0372:             * returned.
0373:             * 
0374:             * @param layer
0375:             *            layer as defined at the capabilities/configuration
0376:             */
0377:            private boolean validate(Layer layer) throws OGCWebServiceException {
0378:
0379:                // why the layer can be null here is not known, but just in case:
0380:                String name = (layer == null) ? "" : layer.getName();
0381:
0382:                // check for valid coordinated reference system
0383:                String[] srs = layer.getSrs();
0384:                boolean tmp = false;
0385:                for (int i = 0; i < srs.length; i++) {
0386:                    if (srs[i].equalsIgnoreCase(getMapRequest.getSrs())) {
0387:                        tmp = true;
0388:                        break;
0389:                    }
0390:                }
0391:
0392:                if (!tmp) {
0393:                    throw new InvalidSRSException(Messages.getMessage(
0394:                            "WMS_INVALIDSRS", name, getMapRequest.getSrs()));
0395:                }
0396:
0397:                // check bounding box
0398:                try {
0399:
0400:                    Envelope bbox = getMapRequest.getBoundingBox();
0401:                    Envelope layerBbox = layer.getLatLonBoundingBox();
0402:                    if (!getMapRequest.getSrs().equalsIgnoreCase("EPSG:4326")) {
0403:                        // transform the bounding box of the request to EPSG:4326
0404:                        GeoTransformer gt = new GeoTransformer(CRSFactory
0405:                                .create("EPSG:4326"));
0406:                        bbox = gt.transform(bbox, reqCRS);
0407:                    }
0408:
0409:                    if (!bbox.intersects(layerBbox)) {
0410:                        return false;
0411:                    }
0412:
0413:                } catch (Exception e) {
0414:                    throw new OGCWebServiceException(Messages
0415:                            .getMessage("WMS_BBOXCOMPARSION"));
0416:                }
0417:
0418:                return true;
0419:            }
0420:
0421:            /**
0422:             * creates a <tt>GetFeatureInfoResult</tt> containing an <tt>OGCWebServiceException</tt>
0423:             * 
0424:             * @param e
0425:             *            exception to encapsulate into the response
0426:             */
0427:            private GetFeatureInfoResult createExceptionResponse(Exception e) {
0428:
0429:                OGCWebServiceException exce = null;
0430:
0431:                // default --> application/vnd.ogc.se_xml
0432:                exce = new OGCWebServiceException(getClass().getName(), e
0433:                        .getMessage());
0434:
0435:                GetFeatureInfoResult res = WMSProtocolFactory
0436:                        .createGetFeatureInfoResponse(request, exce, null);
0437:
0438:                return res;
0439:            }
0440:
0441:            /**
0442:             * waits until the requested layers are available as <tt>DisplayElements</tt> or the time
0443:             * limit has been reached. If the waiting is terminated by reaching the time limit an
0444:             * <tt>WebServiceException</tt> will be thrown to indicated that the request couldn't be
0445:             * performed correctly.
0446:             * 
0447:             * @throws WebServiceException
0448:             *             if the time limit has been reached
0449:             */
0450:            private void waitForFinish() throws OGCWebServiceException,
0451:                    Exception {
0452:
0453:                // subtract 1 second for architecture overhead and image creation
0454:                long timeLimit = 1000 * (configuration.getDeegreeParams()
0455:                        .getRequestTimeLimit() - 1);
0456:                // long timeLimit = 1000 * 100;
0457:                long runTime = 0;
0458:
0459:                while (count < featCol.length) {
0460:                    try {
0461:                        Thread.sleep(100);
0462:                    } catch (Exception e) {
0463:                        LOG.logError("WMS_WAITING_LOOP", e);
0464:                        throw e;
0465:                    }
0466:
0467:                    runTime += 100;
0468:
0469:                    // finish loop after if request performing hasn't been completed
0470:                    // after the time limit is reached
0471:                    if (runTime > timeLimit) {
0472:                        throw new OGCWebServiceException(Messages
0473:                                .getMessage("WMS_TIMEOUT"));
0474:                    }
0475:                }
0476:
0477:            }
0478:
0479:            /**
0480:             * will be called each time a datasource has been read
0481:             * 
0482:             * @param returnValue
0483:             */
0484:            public synchronized void executionFinished(
0485:                    ExecutionFinishedEvent<Object[]> returnValue) {
0486:                Object[] o = null;
0487:                try {
0488:                    o = returnValue.getResult();
0489:                } catch (Throwable t) {
0490:                    LOG.logError("WMS_GETFEATURE_EXCEPTION", t);
0491:                }
0492:                featCol[((Integer) o[0]).intValue()] = o[1];
0493:                increaseCounter();
0494:            }
0495:
0496:            /**
0497:             * generates the desired output from the GMLs
0498:             * 
0499:             * @return the result object
0500:             * @throws OGCWebServiceException
0501:             */
0502:            private GetFeatureInfoResult createFeatureInfoResponse()
0503:                    throws OGCWebServiceException {
0504:
0505:                Envelope bbox = getMapRequest.getBoundingBox();
0506:
0507:                StringBuffer sb = new StringBuffer(20000);
0508:                sb.append("<ll:FeatureCollection ");
0509:
0510:                URL schemaLoc = configuration.getDeegreeParams()
0511:                        .getFeatureSchemaLocation();
0512:                if (schemaLoc != null) {
0513:                    sb.append("xsi:schemaLocation='");
0514:                    sb.append(configuration.getDeegreeParams()
0515:                            .getFeatureSchemaNamespace());
0516:                    sb.append(" ");
0517:                    sb.append(schemaLoc.toExternalForm());
0518:                    sb.append("'");
0519:                }
0520:
0521:                sb.append(" xmlns:gml='http://www.opengis.net/gml' ");
0522:                sb.append("xmlns:ll='http://www.lat-lon.de' ");
0523:                sb
0524:                        .append("xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' ");
0525:                URL url = configuration.getDeegreeParams().getSchemaLocation();
0526:                if (url != null) {
0527:                    sb.append("xsi:schemaLocation='");
0528:                    sb.append("http://www.lat-lon.de "
0529:                            + NetWorker.url2String(url) + "'");
0530:                }
0531:                sb.append("><gml:boundedBy>");
0532:                sb.append("<gml:Box srsName='" + getMapRequest.getSrs() + "'>");
0533:                sb.append("<gml:coordinates>" + bbox.getMin().getX() + ",");
0534:                sb.append(bbox.getMin().getY() + " " + bbox.getMax().getX()
0535:                        + ",");
0536:                sb.append(bbox.getMax().getY() + "</gml:coordinates>");
0537:                sb.append("</gml:Box></gml:boundedBy>");
0538:
0539:                int cnt = 0;
0540:
0541:                for (int i = 0; i < featCol.length; i++) {
0542:                    if (featCol[i] instanceof  OGCWebServiceException) {
0543:                        throw (OGCWebServiceException) featCol[i];
0544:                    }
0545:                    if (featCol[i] != null) {
0546:                        FeatureCollection fc = (FeatureCollection) featCol[i];
0547:                        cnt = appendFeatureCollection(fc, sb, cnt);
0548:                    }
0549:
0550:                    // if ( cnt >= request.getFeatureCount() ) break;
0551:                }
0552:                sb.append("</ll:FeatureCollection>");
0553:
0554:                GetFeatureInfoResult response = WMSProtocolFactory
0555:                        .createGetFeatureInfoResponse(request, null, sb
0556:                                .toString());
0557:
0558:                return response;
0559:            }
0560:
0561:            /**
0562:             * 
0563:             * @param col
0564:             * @param sb
0565:             * @param cnt
0566:             * @return a counter, probably the same that is given as argument
0567:             */
0568:            private int appendFeatureCollection(FeatureCollection col,
0569:                    StringBuffer sb, int cnt) {
0570:
0571:                Feature[] feat = col.toArray();
0572:                if (feat != null) {
0573:                    for (int j = 0; j < feat.length; j++) {
0574:                        FeatureType ft = feat[j].getFeatureType();
0575:                        PropertyType[] ftp = ft.getProperties();
0576:                        cnt++;
0577:                        sb.append("<gml:featureMember>");
0578:                        sb.append("<ll:").append(ft.getName().getLocalName());
0579:                        sb.append(" fid='").append(
0580:                                feat[j].getId().replace(' ', '_')).append("'>");
0581:                        for (int i = 0; i < ftp.length; i++) {
0582:                            if (ftp[i].getType() != Types.GEOMETRY
0583:                                    && ftp[i].getType() != Types.POINT
0584:                                    && ftp[i].getType() != Types.CURVE
0585:                                    && ftp[i].getType() != Types.SURFACE
0586:                                    && ftp[i].getType() != Types.MULTIPOINT
0587:                                    && ftp[i].getType() != Types.MULTICURVE
0588:                                    && ftp[i].getType() != Types.MULTISURFACE) {
0589:
0590:                                FeatureProperty[] props = feat[j]
0591:                                        .getProperties(ftp[i].getName());
0592:                                if (props != null) {
0593:                                    for (FeatureProperty property : props) {
0594:                                        Object value = property.getValue();
0595:                                        sb.append("<ll:"
0596:                                                + ftp[i].getName()
0597:                                                        .getLocalName() + ">");
0598:                                        if (value instanceof  FeatureCollection) {
0599:                                            FeatureCollection fc = (FeatureCollection) value;
0600:                                            appendFeatureCollection(fc, sb, cnt);
0601:                                        } else {
0602:                                            sb.append("<![CDATA[")
0603:                                                    .append(value)
0604:                                                    .append("]]>");
0605:                                        }
0606:                                        sb.append("</ll:"
0607:                                                + ftp[i].getName()
0608:                                                        .getLocalName() + ">");
0609:                                    }
0610:                                }
0611:                            }
0612:                        }
0613:                        sb.append("</ll:").append(ft.getName().getLocalName())
0614:                                .append('>');
0615:                        sb.append("</gml:featureMember>");
0616:                        if (cnt >= request.getFeatureCount())
0617:                            break;
0618:                    }
0619:                }
0620:
0621:                return cnt;
0622:            }
0623:
0624:            // //////////////////////////////////////////////////////////////////////////
0625:            // inner classes //
0626:            // //////////////////////////////////////////////////////////////////////////
0627:
0628:            /**
0629:             * Inner class for accessing the data of one layer and creating a GML document from it. The
0630:             * class extends <tt>Thread</tt> and implements the run method, so that a parallel data
0631:             * accessing from several layers is possible.
0632:             * 
0633:             * @version $Revision: 9697 $
0634:             * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
0635:             */
0636:            public class ServiceInvoker {
0637:                private Layer layer = null;
0638:
0639:                private int index = 0;
0640:
0641:                private AbstractDataSource datasource = null;
0642:
0643:                /**
0644:                 * Creates a new ServiceInvoker object.
0645:                 * 
0646:                 * @param layer
0647:                 * @param datasource
0648:                 * @param index
0649:                 *            index of the requested layer
0650:                 */
0651:                ServiceInvoker(Layer layer, AbstractDataSource datasource,
0652:                        int index) {
0653:                    this .layer = layer;
0654:                    this .index = index;
0655:                    this .datasource = datasource;
0656:                }
0657:
0658:                /**
0659:                 * central method for access the data assigned to a datasource
0660:                 * 
0661:                 * @return result of feature info query
0662:                 */
0663:                public Object run() {
0664:                    Object response = null;
0665:                    if (datasource != null) {
0666:                        OGCWebServiceRequest request = null;
0667:                        try {
0668:                            int type = datasource.getType();
0669:                            switch (type) {
0670:                            case AbstractDataSource.LOCALWFS:
0671:                            case AbstractDataSource.REMOTEWFS: {
0672:                                request = createGetFeatureRequest((LocalWFSDataSource) datasource);
0673:                                break;
0674:                            }
0675:                            case AbstractDataSource.LOCALWCS:
0676:                            case AbstractDataSource.REMOTEWCS: {
0677:                                request = GetMapServiceInvokerForNL
0678:                                        .createGetCoverageRequest(datasource,
0679:                                                getMapRequest);
0680:                                break;
0681:                            }
0682:                            case AbstractDataSource.REMOTEWMS: {
0683:                                request = createGetFeatureInfo(datasource);
0684:                                break;
0685:                            }
0686:                            }
0687:                        } catch (Exception e) {
0688:                            OGCWebServiceException exce = new OGCWebServiceException(
0689:                                    "ServiceInvoker: " + layer.getName(),
0690:                                    Messages.getMessage("WMS_CREATE_QUERY"));
0691:                            response = new Object[] { new Integer(index), exce };
0692:                            LOG.logError(Messages
0693:                                    .getMessage("WMS_CREATE_QUERY")
0694:                                    + ": " + e.getMessage(), e);
0695:                            throw new RuntimeException(e);
0696:                        }
0697:
0698:                        try {
0699:                            Executor executor = Executor.getInstance();
0700:                            DoServiceTask task = new DoServiceTask(datasource
0701:                                    .getOGCWebService(), request);
0702:                            Object o = executor.performSynchronously(task,
0703:                                    datasource.getRequestTimeLimit() * 1000);
0704:                            response = handleResponse(o);
0705:                        } catch (CancellationException e) {
0706:                            // exception can't be re-thrown because responsible GetMapHandler
0707:                            // must collect all responses of all datasources
0708:                            String s = Messages.getMessage(
0709:                                    "WMS_TIMEOUTDATASOURCE", new Integer(
0710:                                            datasource.getRequestTimeLimit()));
0711:                            LOG.logError(s, e);
0712:                            if (datasource.isFailOnException()) {
0713:                                OGCWebServiceException exce = new OGCWebServiceException(
0714:                                        getClass().getName(), s);
0715:                                response = new Object[] { new Integer(index),
0716:                                        exce };
0717:                            } else {
0718:                                response = new Object[] { new Integer(index),
0719:                                        null };
0720:                            }
0721:                        } catch (Throwable t) {
0722:                            // exception can't be re-thrown because responsible GetMapHandler
0723:                            // must collect all responses of all datasources
0724:                            String s = Messages.getMessage(
0725:                                    "WMS_ERRORDOSERVICE", t.getMessage());
0726:                            LOG.logError(s, t);
0727:                            if (datasource.isFailOnException()) {
0728:                                OGCWebServiceException exce = new OGCWebServiceException(
0729:                                        getClass().getName(), s);
0730:                                response = new Object[] { new Integer(index),
0731:                                        exce };
0732:                            } else {
0733:                                response = new Object[] { new Integer(index),
0734:                                        null };
0735:                            }
0736:                        }
0737:
0738:                    }
0739:
0740:                    return response;
0741:
0742:                }
0743:
0744:                /**
0745:                 * creates a getFeature request considering the getMap request and the filterconditions
0746:                 * defined in the submitted <tt>DataSource</tt> object. The request will be encapsualted
0747:                 * within a <tt>OGCWebServiceEvent</tt>.
0748:                 * 
0749:                 * @param ds
0750:                 * @return GetFeature request object
0751:                 */
0752:                private GetFeature createGetFeatureRequest(LocalWFSDataSource ds)
0753:                        throws Exception {
0754:
0755:                    Envelope targetArea = calcTargetArea(ds);
0756:
0757:                    // no filter condition has been defined
0758:                    StringBuffer sb = new StringBuffer(2000);
0759:                    sb.append("<?xml version='1.0' encoding='"
0760:                            + CharsetUtils.getSystemCharset() + "'?>");
0761:                    sb
0762:                            .append("<GetFeature xmlns='http://www.opengis.net/wfs' ");
0763:                    sb.append("xmlns:ogc='http://www.opengis.net/ogc' ");
0764:                    sb.append("xmlns:wfs='http://www.opengis.net/wfs' ");
0765:                    sb.append("xmlns:gml='http://www.opengis.net/gml' ");
0766:                    sb.append("xmlns:").append(ds.getName().getPrefix())
0767:                            .append('=');
0768:                    sb.append("'").append(ds.getName().getNamespace()).append(
0769:                            "' ");
0770:                    sb.append("service='WFS' version='1.1.0' ");
0771:                    sb.append("outputFormat='FEATURECOLLECTION'>");
0772:                    sb.append("<Query typeName='"
0773:                            + ds.getName().getPrefixedName() + "'>");
0774:
0775:                    Query query = ds.getQuery();
0776:
0777:                    // append <wfs:PropertyName> elements
0778:                    if (query != null && query.getPropertyNames() != null) {
0779:                        PropertyPath[] propertyNames = query.getPropertyNames();
0780:                        for (PropertyPath path : propertyNames) {
0781:                            NamespaceContext nsContext = path
0782:                                    .getNamespaceContext();
0783:                            sb.append("<wfs:PropertyName");
0784:                            Map<String, URI> namespaceMap = nsContext
0785:                                    .getNamespaceMap();
0786:                            Iterator<String> prefixIter = namespaceMap.keySet()
0787:                                    .iterator();
0788:                            while (prefixIter.hasNext()) {
0789:                                String prefix = prefixIter.next();
0790:                                if (!CommonNamespaces.XMLNS_PREFIX
0791:                                        .equals(prefix)) {
0792:                                    URI namespace = namespaceMap.get(prefix);
0793:                                    sb.append(" xmlns:" + prefix + "=\""
0794:                                            + namespace + "\"");
0795:                                }
0796:                            }
0797:                            sb.append('>');
0798:                            sb.append(path.getAsString());
0799:                            sb.append("</wfs:PropertyName>");
0800:                        }
0801:                    }
0802:
0803:                    sb.append("<ogc:Filter>");
0804:                    if (query == null) {
0805:                        // BBOX operation for speeding up the search at simple datasources
0806:                        // like shapes
0807:                        sb.append("<ogc:BBOX><PropertyName>");
0808:                        sb.append(ds.getGeometryProperty().getPrefixedName());
0809:                        sb.append("</PropertyName>");
0810:                        sb.append(GMLGeometryAdapter.exportAsBox(targetArea));
0811:                        sb.append("</ogc:BBOX>");
0812:                        sb.append("</ogc:Filter></Query></GetFeature>");
0813:                    } else {
0814:                        Filter filter = query.getFilter();
0815:
0816:                        sb.append("<ogc:And>");
0817:                        // BBOX operation for speeding up the search at simple datasources
0818:                        // like shapes
0819:                        sb.append("<ogc:BBOX><PropertyName>"
0820:                                + ds.getGeometryProperty().getPrefixedName());
0821:                        sb.append("</PropertyName>");
0822:                        sb.append(GMLGeometryAdapter.exportAsBox(targetArea));
0823:                        sb.append("</ogc:BBOX>");
0824:
0825:                        if (filter instanceof  ComplexFilter) {
0826:                            org.deegree.model.filterencoding.Operation op = ((ComplexFilter) filter)
0827:                                    .getOperation();
0828:                            sb.append(op.toXML());
0829:                        } else {
0830:                            ArrayList<FeatureId> featureIds = ((FeatureFilter) filter)
0831:                                    .getFeatureIds();
0832:                            for (int i = 0; i < featureIds.size(); i++) {
0833:                                FeatureId fid = featureIds.get(i);
0834:                                sb.append(fid.toXML());
0835:                            }
0836:                        }
0837:                        sb
0838:                                .append("</ogc:And></ogc:Filter></Query></GetFeature>");
0839:                    }
0840:
0841:                    if (LOG.getLevel() == ILogger.LOG_DEBUG) {
0842:                        LOG.logDebug("GetFeature-request:\n" + sb);
0843:                    }
0844:
0845:                    // create dom representation of the request
0846:                    StringReader sr = new StringReader(sb.toString());
0847:                    Document doc = XMLTools.parse(sr);
0848:
0849:                    // create OGCWebServiceEvent object
0850:                    IDGenerator idg = IDGenerator.getInstance();
0851:                    GetFeature gfr = GetFeature.create(""
0852:                            + idg.generateUniqueID(), doc.getDocumentElement());
0853:
0854:                    return gfr;
0855:                }
0856:
0857:                /**
0858:                 * calculates the target area for the getfeatureinfo request from the maps bounding box, the
0859:                 * its size and the image coordinates of interest. An area is calculated instead of using a
0860:                 * point because to consider uncertainties determining the point of interest
0861:                 * 
0862:                 * @param ds
0863:                 *            <tt>DataSource</tt> of the layer that is requested for feature infos (each
0864:                 *            layer may be offered in its own crs)
0865:                 */
0866:                private Envelope calcTargetArea(AbstractDataSource ds)
0867:                        throws OGCWebServiceException {
0868:
0869:                    int width = request.getGetMapRequestCopy().getWidth();
0870:                    int height = request.getGetMapRequestCopy().getHeight();
0871:                    int x = request.getClickPoint().x;
0872:                    int y = request.getClickPoint().y;
0873:
0874:                    Envelope bbox = request.getGetMapRequestCopy()
0875:                            .getBoundingBox();
0876:
0877:                    // transform request bounding box to the coordinate reference
0878:                    // system the WFS holds the data if requesting CRS and WFS-Data
0879:                    // crs are different
0880:                    // WFService se = (WFService)ds.getOGCWebService();
0881:                    // WFSCapabilities capa = (WFSCapabilities)se.getWFSCapabilities();
0882:                    //            
0883:                    // org.deegree.ogcwebservices.wfs.capabilities.FeatureType ft =
0884:                    // capa.getFeatureTypeList().getFeatureType( ds.getName() );
0885:                    WFService se = (WFService) ds.getOGCWebService();
0886:                    WFSCapabilities capa = se.getCapabilities();
0887:                    QualifiedName gn = ds.getName();
0888:                    WFSFeatureType ft = capa.getFeatureTypeList()
0889:                            .getFeatureType(gn);
0890:
0891:                    if (ft == null) {
0892:                        throw new OGCWebServiceException(Messages.getMessage(
0893:                                "WMS_UNKNOWNFT", ds.getName()));
0894:                    }
0895:                    String crs = ft.getDefaultSRS().toASCIIString();
0896:                    Envelope tBbox = null;
0897:                    try {
0898:                        GeoTransform gt = new WorldToScreenTransform(bbox
0899:                                .getMin().getX(), bbox.getMin().getY(), bbox
0900:                                .getMax().getX(), bbox.getMax().getY(), 0, 0,
0901:                                width - 1, height - 1);
0902:                        double[] target = new double[4];
0903:                        int rad = configuration.getDeegreeParams()
0904:                                .getFeatureInfoRadius();
0905:                        target[0] = gt.getSourceX(x - rad);
0906:                        target[1] = gt.getSourceY(y + rad);
0907:                        target[2] = gt.getSourceX(x + rad);
0908:                        target[3] = gt.getSourceY(y - rad);
0909:
0910:                        tBbox = GeometryFactory.createEnvelope(target[0],
0911:                                target[1], target[2], target[3], null);
0912:                        if (!(crs.equalsIgnoreCase(request
0913:                                .getGetMapRequestCopy().getSrs()))) {
0914:                            GeoTransformer transformer = new GeoTransformer(
0915:                                    CRSFactory.create(crs));
0916:                            tBbox = transformer.transform(tBbox, reqCRS);
0917:                        }
0918:
0919:                    } catch (Exception e) {
0920:                        throw new OGCWebServiceException(e.toString());
0921:                    }
0922:
0923:                    return tBbox;
0924:                }
0925:
0926:                /**
0927:                 * creates a GetFeatureInfo request for requesting a cascaded remote WMS The request will be
0928:                 * encapsualted within a <tt>OGCWebServiceEvent</tt>.
0929:                 * 
0930:                 * @param ds
0931:                 * @return GetFeatureInfo request object
0932:                 */
0933:                private GetFeatureInfo createGetFeatureInfo(
0934:                        AbstractDataSource ds) {
0935:
0936:                    // create embbeded map request
0937:                    GetMap gmr = ((RemoteWMSDataSource) ds).getGetMapRequest();
0938:
0939:                    String format = getMapRequest.getFormat();
0940:
0941:                    if (gmr != null && !"%default%".equals(gmr.getFormat())) {
0942:                        format = gmr.getFormat();
0943:                    }
0944:
0945:                    org.deegree.ogcwebservices.wms.operation.GetMap.Layer[] lys = null;
0946:                    lys = new org.deegree.ogcwebservices.wms.operation.GetMap.Layer[1];
0947:                    lys[0] = GetMap.createLayer(layer.getName(), "$DEFAULT");
0948:
0949:                    if (gmr != null && gmr.getLayers() != null) {
0950:                        lys = gmr.getLayers();
0951:                    }
0952:                    Color bgColor = getMapRequest.getBGColor();
0953:                    if (gmr != null && gmr.getBGColor() != null) {
0954:                        bgColor = gmr.getBGColor();
0955:                    }
0956:                    Values time = getMapRequest.getTime();
0957:                    if (gmr != null && gmr.getTime() != null) {
0958:                        time = gmr.getTime();
0959:                    }
0960:                    Map<String, String> vendorSpecificParameter = getMapRequest
0961:                            .getVendorSpecificParameters();
0962:                    if (gmr != null
0963:                            && gmr.getVendorSpecificParameters() != null
0964:                            && gmr.getVendorSpecificParameters().size() > 0) {
0965:                        vendorSpecificParameter = gmr
0966:                                .getVendorSpecificParameters();
0967:                    }
0968:                    String version = "1.1.0";
0969:                    if (gmr != null && gmr.getVersion() != null) {
0970:                        version = gmr.getFormat();
0971:                    }
0972:                    Values elevation = getMapRequest.getElevation();
0973:                    if (gmr != null && gmr.getElevation() != null) {
0974:                        elevation = gmr.getElevation();
0975:                    }
0976:                    Map<String, Values> sampleDim = null;
0977:                    if (gmr != null && gmr.getSampleDimension() != null) {
0978:                        sampleDim = gmr.getSampleDimension();
0979:                    }
0980:
0981:                    IDGenerator idg = IDGenerator.getInstance();
0982:                    gmr = GetMap.create(version, "" + idg.generateUniqueID(),
0983:                            lys, elevation, sampleDim, format, getMapRequest
0984:                                    .getWidth(), getMapRequest.getHeight(),
0985:                            getMapRequest.getSrs(), getMapRequest
0986:                                    .getBoundingBox(), getMapRequest
0987:                                    .getTransparency(), bgColor, getMapRequest
0988:                                    .getExceptions(), time, null, null,
0989:                            vendorSpecificParameter);
0990:
0991:                    // create GetFeatureInfo request for cascaded/remote WMS
0992:                    String[] queryLayers = new String[] { ds.getName()
0993:                            .getPrefixedName() };
0994:                    GetFeatureInfo req = GetFeatureInfo.create("1.1.0", this 
0995:                            .toString(), queryLayers, gmr,
0996:                            "application/vnd.ogc.gml", request
0997:                                    .getFeatureCount(),
0998:                            request.getClickPoint(), request.getExceptions(),
0999:                            null, request.getVendorSpecificParameters());
1000:
1001:                    try {
1002:                        LOG.logDebug("cascaded GetFeatureInfo request: ", req
1003:                                .getRequestParameter());
1004:                    } catch (OGCWebServiceException e) {
1005:                        LOG.logError(e.getMessage(), e);
1006:                    }
1007:
1008:                    return req;
1009:                }
1010:
1011:                /**
1012:                 * The method implements the <tt>OGCWebServiceClient</tt> interface. So a deegree OWS
1013:                 * implementation accessed by this class is able to return the result of a request by
1014:                 * calling the write-method.
1015:                 * 
1016:                 * @param result
1017:                 *            to a GetXXX request
1018:                 * @return the response object
1019:                 * @throws Exception
1020:                 */
1021:                private Object handleResponse(Object result) throws Exception {
1022:                    Object[] response = null;
1023:                    if (result instanceof  FeatureResult) {
1024:                        response = handleGetFeatureResponse((FeatureResult) result);
1025:                    } else if (result instanceof  ResultCoverage) {
1026:                        response = handleGetCoverageResponse((ResultCoverage) result);
1027:                    } else if (result instanceof  GetFeatureInfoResult) {
1028:
1029:                        response = handleGetFeatureInfoResult((GetFeatureInfoResult) result);
1030:                    } else {
1031:                        throw new Exception(Messages
1032:                                .getMessage("WMS_UNKNOWNRESPONSEFORMAT"));
1033:                    }
1034:                    return response;
1035:                }
1036:
1037:                /**
1038:                 * handles the response of a WFS and calls a factory to create <tt>DisplayElement</tt> and
1039:                 * a <tt>Theme</tt> from it
1040:                 * 
1041:                 * @param response
1042:                 * @return the response objects
1043:                 * @throws Exception
1044:                 */
1045:                private Object[] handleGetFeatureResponse(FeatureResult response)
1046:                        throws Exception {
1047:                    FeatureCollection fc = null;
1048:
1049:                    Object o = response.getResponse();
1050:                    if (o instanceof  FeatureCollection) {
1051:                        fc = (FeatureCollection) o;
1052:                    } else if (o.getClass() == byte[].class) {
1053:                        Reader reader = new InputStreamReader(
1054:                                new ByteArrayInputStream((byte[]) o));
1055:                        GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
1056:                        doc.load(reader, XMLFragment.DEFAULT_URL);
1057:                        fc = doc.parse();
1058:                    } else {
1059:                        throw new Exception(Messages
1060:                                .getMessage("WMS_UNKNOWNDATAFORMATFT"));
1061:                    }
1062:                    Object[] ro = new Object[2];
1063:                    ro[0] = new Integer(index);
1064:                    ro[1] = fc;
1065:                    return ro;
1066:                }
1067:
1068:                /**
1069:                 * 
1070:                 * @param res
1071:                 */
1072:                private Object[] handleGetFeatureInfoResult(
1073:                        GetFeatureInfoResult res) throws Exception {
1074:
1075:                    FeatureCollection fc = null;
1076:                    StringReader sr = new StringReader(res.getFeatureInfo());
1077:                    XMLFragment xml = new XMLFragment(sr,
1078:                            XMLFragment.DEFAULT_URL);
1079:
1080:                    if (LOG.getLevel() == ILogger.LOG_DEBUG) {
1081:                        LOG
1082:                                .logDebug("GetFeature-response (before transformation): "
1083:                                        + xml.getAsPrettyString());
1084:                    }
1085:
1086:                    URL url = ((RemoteWMSDataSource) datasource)
1087:                            .getFeatureInfoTransform();
1088:                    if (url != null) {
1089:                        // transform incoming GML/XML to a GML application schema
1090:                        // that is understood by deegree
1091:                        XSLTDocument xslt = new XSLTDocument();
1092:                        xslt.load(url);
1093:                        xml = xslt.transform(xml, null, null, null);
1094:                    }
1095:                    GMLFeatureCollectionDocument doc = new GMLFeatureCollectionDocument();
1096:                    doc.setRootElement(xml.getRootElement());
1097:                    fc = doc.parse();
1098:                    Object[] ro = new Object[2];
1099:                    ro[0] = new Integer(index);
1100:                    ro[1] = fc;
1101:                    return ro;
1102:                }
1103:
1104:                private Object[] handleGetCoverageResponse(
1105:                        ResultCoverage response) throws OGCWebServiceException {
1106:                    ImageGridCoverage gc = (ImageGridCoverage) response
1107:                            .getCoverage();
1108:                    Object[] result = new Object[2];
1109:                    if (gc != null) {
1110:                        BufferedImage bi = gc.getAsImage(-1, -1);
1111:
1112:                        float[][] data = new Image2RawData(bi).parse();
1113:
1114:                        double scaleX = (double) data[0].length
1115:                                / (double) getMapRequest.getWidth();
1116:                        double scaleY = (double) data.length
1117:                                / (double) getMapRequest.getHeight();
1118:                        int pxSizeX = (int) Math.round(scaleX);
1119:                        int pxSizeY = (int) Math.round(scaleY);
1120:                        if (pxSizeX == 0) {
1121:                            pxSizeX = 1;
1122:                        }
1123:                        if (pxSizeY == 0) {
1124:                            pxSizeY = 1;
1125:                        }
1126:
1127:                        LOG.logDebug("Size of grid coverage is "
1128:                                + data[0].length + "x" + data.length + ".");
1129:                        LOG.logDebug("Returning an area of " + pxSizeX + "x"
1130:                                + pxSizeY + " pixels.");
1131:
1132:                        int ix = (int) (request.getClickPoint().x * scaleX)
1133:                                - pxSizeX / 2;
1134:                        int iy = (int) (request.getClickPoint().y * scaleY)
1135:                                - pxSizeY / 2;
1136:
1137:                        // some checks to avoid areas that are not requestable
1138:                        if (ix < 0) {
1139:                            ix = 0;
1140:                        }
1141:                        if (iy < 0) {
1142:                            iy = 0;
1143:                        }
1144:                        if (ix >= (data[0].length - pxSizeX)) {
1145:                            ix = data[0].length - pxSizeX - 1;
1146:                        }
1147:                        if (iy >= (data.length - pxSizeY)) {
1148:                            iy = data.length - pxSizeY - 1;
1149:                        }
1150:
1151:                        FeatureCollection fc = FeatureFactory
1152:                                .createFeatureCollection(gc
1153:                                        .getCoverageOffering().getName(),
1154:                                        pxSizeX * pxSizeY);
1155:
1156:                        PropertyType pt = null;
1157:                        try {
1158:                            pt = FeatureFactory.createPropertyType(VALUE,
1159:                                    new QualifiedName("xsd", "double",
1160:                                            CommonNamespaces.XSNS), 1, 1);
1161:                        } catch (UnknownTypeException e) {
1162:                            LOG
1163:                                    .logError(
1164:                                            "The xsd:double type is not known?!? Get a new deegree.jar!",
1165:                                            e);
1166:                        }
1167:                        FeatureType ft = FeatureFactory.createFeatureType(gc
1168:                                .getCoverageOffering().getName(), false,
1169:                                new PropertyType[] { pt });
1170:
1171:                        for (int x = ix; x < ix + pxSizeX; ++x) {
1172:                            for (int y = iy; y < iy + pxSizeY; ++y) {
1173:                                FeatureProperty p = FeatureFactory
1174:                                        .createFeatureProperty(VALUE,
1175:                                                new Double(data[y][x]));
1176:                                Feature f = FeatureFactory.createFeature(
1177:                                        "ID_faked_for_" + x + "x" + y, ft,
1178:                                        new FeatureProperty[] { p });
1179:                                fc.add(f);
1180:                            }
1181:                        }
1182:
1183:                        result[1] = fc;
1184:                    } else {
1185:                        throw new OGCWebServiceException(getClass().getName(),
1186:                                Messages.getMessage("WMS_NOCOVERAGE",
1187:                                        datasource.getName()));
1188:                    }
1189:
1190:                    result[0] = new Integer(index);
1191:                    return result;
1192:                }
1193:
1194:            }
1195:
1196:            private class DoServiceTask implements  Callable<Object> {
1197:
1198:                OGCWebService webService;
1199:
1200:                OGCWebServiceRequest request;
1201:
1202:                DoServiceTask(OGCWebService webService,
1203:                        OGCWebServiceRequest request) {
1204:                    this .webService = webService;
1205:                    this .request = request;
1206:                }
1207:
1208:                public Object call() throws Exception {
1209:                    return this .webService.doService(request);
1210:                }
1211:            }
1212:
1213:            private class ServiceInvokerTask implements  Callable<Object[]> {
1214:
1215:                ServiceInvoker invoker;
1216:
1217:                ServiceInvokerTask(ServiceInvoker invoker) {
1218:                    this .invoker = invoker;
1219:                }
1220:
1221:                public Object[] call() throws Exception {
1222:                    return (Object[]) this.invoker.run();
1223:                }
1224:            }
1225:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.