/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wms; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.geoserver.platform.ServiceException; import org.geotools.data.Query; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.GeoTools; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.styling.Style; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; import org.opengis.referencing.crs.CoordinateReferenceSystem; import com.vividsolutions.jts.geom.Envelope; /** * Wraps the large number of information normally extracted from a feature info request into a * single object, provides facilities to access extra information about the current layer (view * parameters, styles) * * @author Andrea Aime - GeoSolutions */ public class FeatureInfoRequestParameters { int x; int y; int buffer; List<Map<String, String>> viewParams; GetMapRequest getMapReq; CoordinateReferenceSystem requestedCRS; int width; int height; ReferencedEnvelope bbox; double scaleDenominator; List<Filter> filters; List<MapLayerInfo> layers; List<Style> styles; List<Object> elevations; List<Object> times; FilterFactory2 ff; private List<List<String>> propertyNames; int currentLayer = 0; int maxFeatures; public FeatureInfoRequestParameters(GetFeatureInfoRequest request) { // use the layer of the QUERY_LAYERS parameter, not the LAYERS one this.layers = request.getQueryLayers(); this.filters = request.getGetMapRequest().getFilter(); this.styles = getStyles(request, layers); this.x = request.getXPixel(); this.y = request.getYPixel(); this.buffer = request.getGetMapRequest().getBuffer(); this.viewParams = request.getGetMapRequest().getViewParams(); this.getMapReq = request.getGetMapRequest(); this.requestedCRS = getMapReq.getCrs(); // optional, may be null this.maxFeatures = request.getFeatureCount(); // basic information about the request this.width = getMapReq.getWidth(); this.height = getMapReq.getHeight(); this.bbox = new ReferencedEnvelope(getMapReq.getBbox(), getMapReq.getCrs()); this.scaleDenominator = getScaleDenominator(request.getGetMapRequest()); this.elevations = request.getGetMapRequest().getElevation(); this.times = request.getGetMapRequest().getTime(); this.ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); this.propertyNames = request.getPropertyNames(); } private double getScaleDenominator(GetMapRequest request) { final Envelope envelope = request.getBbox(); final CoordinateReferenceSystem mapcrs = request.getCrs(); WMSMapContent mapContent = new WMSMapContent(request); if (mapcrs != null) { mapContent.getViewport().setBounds(new ReferencedEnvelope(envelope, mapcrs)); } else { mapContent.getViewport().setBounds( new ReferencedEnvelope(envelope, DefaultGeographicCRS.WGS84)); } mapContent.setMapWidth(request.getWidth()); mapContent.setMapHeight(request.getHeight()); mapContent.setAngle(request.getAngle()); return mapContent.getScaleDenominator(true); } /** * Grab the list of styles for each query layer, we'll use them to auto-evaluate the * GetFeatureInfo radius if the user did not specify one * * @param request * @param layers * */ private List<Style> getStyles(final GetFeatureInfoRequest request, List<MapLayerInfo> layers) { List<Style> getMapStyles = request.getGetMapRequest().getStyles(); List<Style> styles = new ArrayList<Style>(); List<MapLayerInfo> getMapLayers = request.getGetMapRequest().getLayers(); for (int i = 0; i < layers.size(); i++) { final String targetLayer = layers.get(i).getName(); Style s = null; for (int j = 0; j < getMapLayers.size(); j++) { if (getMapLayers.get(j).getName().equals(targetLayer)) { if (getMapStyles != null && getMapStyles.size() > j) { s = getMapStyles.get(j); } else { s = getMapLayers.get(j).getDefaultStyle(); } break; } } if(s != null) { styles.add(s); } else { throw new ServiceException("Failed to locate style for layer " + targetLayer); } } return styles; } /** * Moves to the next requested layer */ void nextLayer() { currentLayer++; } /** * Returns the current layer * * */ public MapLayerInfo getLayer() { return layers.get(currentLayer); } public Style getStyle() { return styles.get(currentLayer); } public Filter getFilter() { if(filters == null || filters.size() <= currentLayer) { return null; } else { return filters.get(currentLayer); } } /** * The property names for the specified layer (if any, null otherwise) * * */ public String[] getPropertyNames() { if (propertyNames == null || propertyNames.size() == 0 || propertyNames.get(currentLayer) == null) { return Query.ALL_NAMES; } else { List<String> layerPropNames = propertyNames.get(currentLayer); return layerPropNames.toArray(new String[layerPropNames.size()]); } } /** * The view parameters for the current layer * * */ public Map<String, String> getViewParams() { if (viewParams == null || viewParams.size() < currentLayer) { return null; } else { return viewParams.get(currentLayer); } } /** * The x of the clicked pixel on the raster output map */ public int getX() { return x; } /** * The y of the clicked pixel on the raster output map */ public int getY() { return y; } /** * The buffer, as specified by the user */ public int getBuffer() { return buffer; } /** * The requested coordinate reference system * * */ public CoordinateReferenceSystem getRequestedCRS() { return requestedCRS; } /** * Pixel width of the requested map */ public int getWidth() { return width; } /** * Pixel width of the requested map */ public int getHeight() { return height; } /** * Real world bounds of the requested map */ public ReferencedEnvelope getRequestedBounds() { return bbox; } /** * The scale denominator of the requested map */ public double getScaleDenominator() { return scaleDenominator; } /** * The elevations in the request (if any) */ public List<Object> getElevations() { return elevations; } /** * The elevations in the request (if any) */ public List<Object> getTimes() { return times; } /** * A filter factory suitable to build filters * * */ public FilterFactory2 getFilterFactory() { return ff; } /** * The GetMap request wrapped by the GetFeatureInfo one * * */ public GetMapRequest getGetMapRequest() { return getMapReq; } }