/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.vfny.geoserver.wms.responses.featureInfo; import java.util.List; import org.geoserver.platform.ServiceException; import org.geoserver.wms.MapLayerInfo; import org.geotools.styling.Style; import org.opengis.filter.Filter; import org.vfny.geoserver.Request; import org.vfny.geoserver.Response; import org.vfny.geoserver.wms.WmsException; import org.vfny.geoserver.wms.requests.GetFeatureInfoRequest; /** * Base class for GetFeatureInfo delegates responsible of creating * GetFeatureInfo responses in different formats. * * <p> * Subclasses should implement one or more output formats, wich will be * returned in a list of mime type strings in * <code>getSupportedFormats</code>. For example, a subclass can be created to * write one of the following output formats: * * <ul> * <li> * text/plain * </li> * <li> * text/html * </li> * </ul> * </p> * * <p> * This abstract class takes care of executing the request in the sense of * taking the GetFeatureInfo request parameters such as query_layers, bbox, x, * y, etc., create the gt2 query objects for each featuretype and executing * it. This process leads to a set of FeatureResults objects and its metadata, * wich will be given to the <code>execute(FeatureTypeInfo[] , * FeatureResults[])</code> method, that a subclass should implement as a * matter of setting up any resource/state it needs to later encoding. * </p> * * <p> * So, it should be enough to a subclass to implement the following methods in * order to produce the requested output format: * * <ul> * <li> * execute(FeatureTypeInfo[], FeatureResults[], int, int) * </li> * <li> * canProduce(String mapFormat) * </li> * <li> * getSupportedFormats() * </li> * <li> * writeTo(OutputStream) * </li> * </ul> * </p> * * @author Gabriel Roldan, Axios Engineering * @author Chris Holmes * @version $Id$ */ public abstract class GetFeatureInfoDelegate implements Response { /** DOCUMENT ME! */ private GetFeatureInfoRequest request; /** * Creates a new GetMapDelegate object. */ public GetFeatureInfoDelegate() { } /** * Executes a Request, which must be a GetMapRequest. Any other will cause * a class cast exception. * * @param request A valid GetMapRequest. * * @throws ServiceException If the request can not be executed. */ public void execute(Request request) throws ServiceException { execute((GetFeatureInfoRequest) request); } /** * Executes a GetFeatureInfo request. Builds the proper objects from the * request names. * * @param request A valid GetMapRequest. * * @throws WmsException If anything goes wrong. */ protected void execute(GetFeatureInfoRequest request) throws WmsException { this.request = request; //use the layer of the QUERY_LAYERS parameter, not the LAYERS one MapLayerInfo[] layers = request.getQueryLayers(); // grab the list of filters from the GetMap request, we don't want // to return what the user explicitly excluded List filterList = request.getGetMapRequest().getFilter(); Filter[] filters; if (filterList != null && filterList.size() > 0) { filters = (Filter[]) filterList.toArray(new Filter[filterList.size()]); } else { filters = new Filter[layers.length]; } // 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 List<Style> getMapStyles = request.getGetMapRequest().getStyles(); Style[] styles = new Style[layers.length]; for (int i = 0; i < styles.length; i++) { MapLayerInfo[] getMapLayers = request.getGetMapRequest().getLayers(); final String targetLayer = layers[i].getName(); for (int j = 0; j < getMapLayers.length; j++) { if(getMapLayers[j].getName().equals(targetLayer)) { if(getMapStyles != null && getMapStyles.size() > 0) styles[i] = (Style) getMapStyles.get(j); if(styles[i] == null) styles[i] = getMapLayers[j].getDefaultStyle(); break; } } } // delegate to subclasses the hard work int x = request.getXPixel(); int y = request.getYPixel(); int buffer = request.getGetMapRequest().getBuffer(); execute(layers, styles, filters, x, y, buffer); } /** * Execute method for concrete children to implement. Each param is an * array in the order things should be processed. * * @param requestedLayers Array of config information of the FeatureTypes * to be processed. * @param styles Matching array of layer styles * @param filters Matching array of layer definition filters * @param x the X coordinate in pixels where the identification must be * done relative to the image dimensions * @param y the Y coordinate in pixels where the identification must be * done relative to the image dimensions * @param the user specified buffer * * @throws WmsException For any problems executing. */ protected abstract void execute(MapLayerInfo[] requestedLayers, Style[] styles, Filter[] filters, int x, int y, int buffer) throws WmsException; /** * Gets the map request. Used by delegate children to find out more * information about the request. * * @return The request to be processed. */ protected GetFeatureInfoRequest getRequest() { return this.request; } /** * Evaluates if this GetFeatureInfo producer can generate the map format * specified by <code>mapFormat</code>, where <code>mapFormat</code> is * the MIME type of the requested response. * * @param mapFormat the MIME type of the output map format requiered * * @return true if class can produce a map in the passed format */ public boolean canProduce(String mapFormat) { return getSupportedFormats().contains(mapFormat); } /** * Gets A list of the formats this delegate supports. * * @return A list of strings of the formats supported. */ public abstract List getSupportedFormats(); }